From a7cafd1f2448aa1c1761ae44454cb09529f68d3b Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 21 Apr 2023 21:27:08 +0400 Subject: [PATCH 001/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f98be845..aa8b32ec3 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 6.6! +##

Supported Bot API version: 6.7!

Official documentation

Official ru documentation

From d1417e561676bbef7ebe536747a669e4aacc93c6 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 21 Apr 2023 22:14:16 +0400 Subject: [PATCH 002/480] Added the field web_app_name to the class WriteAccessAllowed. --- telebot/types.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 22d46c937..fed442c03 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7396,13 +7396,20 @@ class WriteAccessAllowed(JsonDeserializable): Currently holds no information. Telegram documentation: https://core.telegram.org/bots/api#writeaccessallowed + + :param web_app_name: Optional. Name of the Web App which was launched from a link + :type web_app_name: :obj:`str` """ @classmethod def de_json(cls, json_string): - return cls() + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + - def __init__(self) -> None: - pass + def __init__(self, web_app_name: str) -> None: + self.web_app_name: str = web_app_name + class UserShared(JsonDeserializable): From 966b45186906805a012a58c32600e077629b4589 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 21 Apr 2023 22:28:20 +0400 Subject: [PATCH 003/480] Added the field switch_inline_query_chosen_chat of the type SwitchInlineQueryChosenChat to the class InlineKeyboardButton, which allows bots to switch to inline mode in a chosen chat of the given type. --- telebot/types.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index fed442c03..f23d7fc5b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2592,6 +2592,10 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable) something from multiple options. :type switch_inline_query_current_chat: :obj:`str` + :param switch_inline_query_chosen_chat: 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 query in the input field + :type switch_inline_query_chosen_chat: :class:`telebot.types.SwitchInlineQueryChosenChat` + :param callback_game: Optional. Description of the game that will be launched when the user presses the button. NOTE: This type of button must always be the first button in the first row. :type callback_game: :class:`telebot.types.CallbackGame` @@ -2611,17 +2615,20 @@ def de_json(cls, json_string): obj['login_url'] = LoginUrl.de_json(obj.get('login_url')) if 'web_app' in obj: obj['web_app'] = WebAppInfo.de_json(obj.get('web_app')) + if 'switch_inline_query_chosen_chat' in obj: + obj['switch_inline_query_chosen_chat'] = SwitchInlineQueryChosenChat.de_json(obj.get('switch_inline_query_chosen_chat')) return cls(**obj) def __init__(self, text, url=None, callback_data=None, web_app=None, switch_inline_query=None, - switch_inline_query_current_chat=None, callback_game=None, pay=None, login_url=None, **kwargs): + switch_inline_query_current_chat=None, switch_inline_query_chosen_chat=None, callback_game=None, pay=None, login_url=None, **kwargs): self.text: str = text self.url: str = url self.callback_data: str = callback_data self.web_app: WebAppInfo = web_app self.switch_inline_query: str = switch_inline_query self.switch_inline_query_current_chat: str = switch_inline_query_current_chat + self.switch_inline_query_chosen_chat: SwitchInlineQueryChosenChat = switch_inline_query_chosen_chat self.callback_game = callback_game # Not Implemented self.pay: bool = pay self.login_url: LoginUrl = login_url @@ -2647,6 +2654,8 @@ def to_dict(self): json_dict['pay'] = self.pay if self.login_url is not None: json_dict['login_url'] = self.login_url.to_dict() + if self.switch_inline_query_chosen_chat is not None: + json_dict['switch_inline_query_chosen_chat'] = self.switch_inline_query_chosen_chat.to_dict() return json_dict @@ -7583,4 +7592,64 @@ def convert_input_sticker(self): return self.to_json(), {self._sticker_name: self.sticker} - \ No newline at end of file + +class SwitchInlineQueryChosenChat(JsonDeserializable, Dictionaryable, JsonSerializable): + """ + Represents an inline button that switches the current user to inline mode in a chosen chat, + with an optional default inline query. + + Telegram Documentation: https://core.telegram.org/bots/api#inlinekeyboardbutton + + :param query: Optional. The default inline query to be inserted in the input field. + If left empty, only the bot's username will be inserted + :type query: :obj:`str` + + :param allow_user_chats: Optional. True, if private chats with users can be chosen + :type allow_user_chats: :obj:`bool` + + :param allow_bot_chats: Optional. True, if private chats with bots can be chosen + :type allow_bot_chats: :obj:`bool` + + :param allow_group_chats: Optional. True, if group and supergroup chats can be chosen + :type allow_group_chats: :obj:`bool` + + :param allow_channel_chats: Optional. True, if channel chats can be chosen + :type allow_channel_chats: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`SwitchInlineQueryChosenChat` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, query=None, allow_user_chats=None, allow_bot_chats=None, allow_group_chats=None, + allow_channel_chats=None): + self.query: str = query + self.allow_user_chats: bool = allow_user_chats + self.allow_bot_chats: bool = allow_bot_chats + self.allow_group_chats: bool = allow_group_chats + self.allow_channel_chats: bool = allow_channel_chats + + def to_dict(self): + json_dict = {} + + if self.query is not None: + json_dict['query'] = self.query + if self.allow_user_chats is not None: + json_dict['allow_user_chats'] = self.allow_user_chats + if self.allow_bot_chats is not None: + json_dict['allow_bot_chats'] = self.allow_bot_chats + if self.allow_group_chats is not None: + json_dict['allow_group_chats'] = self.allow_group_chats + if self.allow_channel_chats is not None: + json_dict['allow_channel_chats'] = self.allow_channel_chats + + return json_dict + + def to_json(self): + return json.dumps(self.to_dict()) From d6f4987197d9450d10a4c823f72cb67bbd832cc8 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 21 Apr 2023 22:30:32 +0400 Subject: [PATCH 004/480] Added the field via_chat_folder_invite_link to the class ChatMemberUpdated. --- telebot/types.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index f23d7fc5b..53b692d65 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -237,6 +237,9 @@ class ChatMemberUpdated(JsonDeserializable): link events only. :type invite_link: :class:`telebot.types.ChatInviteLink` + :param via_chat_folder_invite_link: Optional. True, if the user joined the chat via a chat folder invite link + :type via_chat_folder_invite_link: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberUpdated` """ @@ -251,13 +254,15 @@ def de_json(cls, json_string): obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link')) return cls(**obj) - def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, **kwargs): + def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, via_chat_folder_invite_link=None, + **kwargs): self.chat: Chat = chat self.from_user: User = from_user self.date: int = date self.old_chat_member: ChatMember = old_chat_member self.new_chat_member: ChatMember = new_chat_member self.invite_link: Optional[ChatInviteLink] = invite_link + self.via_chat_folder_invite_link: Optional[bool] = via_chat_folder_invite_link @property def difference(self) -> Dict[str, List]: From 77e19286280c312be6802583d66d03e14d3ee35c Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 22 Apr 2023 18:25:24 +0400 Subject: [PATCH 005/480] Added the ability to set different bot names for different user languages using the method setMyName. --- telebot/__init__.py | 26 ++++++++++++++++++++++++++ telebot/apihelper.py | 9 +++++++++ telebot/async_telebot.py | 18 ++++++++++++++++++ telebot/asyncio_helper.py | 10 ++++++++++ 4 files changed, 63 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index c385a295f..549a69de9 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3443,6 +3443,24 @@ def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, """ result = apihelper.get_my_commands(self.token, scope, language_code) return [types.BotCommand.de_json(cmd) for cmd in result] + + def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=None): + """ + Use this method to change the bot's name. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setmyname + + :param name: Optional. New bot name; 0-64 characters. Pass an empty string to remove the dedicated name for the given language. + :type name: :obj:`str` + + :param language_code: Optional. A two-letter ISO 639-1 language code. If empty, the name will be shown to all users for whose + language there is no dedicated name. + :type language_code: :obj:`str` + + :return: True on success. + """ + + return apihelper.set_my_name(self.token, name, language_code) def set_my_description(self, description: Optional[str]=None, language_code: Optional[str]=None): """ @@ -3450,6 +3468,8 @@ def set_my_description(self, description: Optional[str]=None, language_code: Opt the chat with the bot if the chat is empty. Returns True on success. + Telegram documentation: https://core.telegram.org/bots/api#setmydescription + :param description: New bot description; 0-512 characters. Pass an empty string to remove the dedicated description for the given language. :type description: :obj:`str` @@ -3467,6 +3487,8 @@ def get_my_description(self, language_code: Optional[str]=None): Use this method to get the current bot description for the given user language. Returns BotDescription on success. + Telegram documentation: https://core.telegram.org/bots/api#getmydescription + :param language_code: A two-letter ISO 639-1 language code or an empty string :type language_code: :obj:`str` @@ -3481,6 +3503,8 @@ def set_my_short_description(self, short_description:Optional[str]=None, languag is sent together with the link when users share the bot. Returns True on success. + Telegram documentation: https://core.telegram.org/bots/api#setmyshortdescription + :param short_description: New short description for the bot; 0-120 characters. Pass an empty string to remove the dedicated short description for the given language. :type short_description: :obj:`str` @@ -3498,6 +3522,8 @@ def get_my_short_description(self, language_code: Optional[str]=None): Use this method to get the current bot short description for the given user language. Returns BotShortDescription on success. + Telegram documentation: https://core.telegram.org/bots/api#getmyshortdescription + :param language_code: A two-letter ISO 639-1 language code or an empty string :type language_code: :obj:`str` diff --git a/telebot/apihelper.py b/telebot/apihelper.py index b5eb0651c..8d2b1e72e 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1196,6 +1196,15 @@ def get_my_commands(token, scope=None, language_code=None): payload['language_code'] = language_code return _make_request(token, method_url, params=payload) +def set_my_name(token, name=None, language_code=None): + method_url = r'setMyName' + payload = {} + if name is not None: + payload['name'] = name + if language_code is not None: + payload['language_code'] = language_code + return _make_request(token, method_url, params=payload, method='post') + def set_chat_menu_button(token, chat_id=None, menu_button=None): method_url = r'setChatMenuButton' payload = {} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ebf5e80d6..242e74c4b 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4361,6 +4361,24 @@ async def get_my_commands(self, scope: Optional[types.BotCommandScope], result = await asyncio_helper.get_my_commands(self.token, scope, language_code) return [types.BotCommand.de_json(cmd) for cmd in result] + async def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=None): + """ + Use this method to change the bot's name. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setmyname + + :param name: Optional. New bot name; 0-64 characters. Pass an empty string to remove the dedicated name for the given language. + :type name: :obj:`str` + + :param language_code: Optional. A two-letter ISO 639-1 language code. If empty, the name will be shown to all users for whose + language there is no dedicated name. + :type language_code: :obj:`str` + + :return: True on success. + """ + + return await asyncio_helper.set_my_name(self.token, name, language_code) + async def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 6f7ef0f84..804e51654 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1183,6 +1183,16 @@ async def get_my_commands(token, scope=None, language_code=None): payload['language_code'] = language_code return await _process_request(token, method_url, params=payload) + +async def set_my_name(token, name=None, language_code=None): + method_url = r'setMyName' + payload = {} + if name is not None: + payload['name'] = name + if language_code is not None: + payload['language_code'] = language_code + return await _process_request(token, method_url, params=payload, method='post') + async def set_chat_menu_button(token, chat_id=None, menu_button=None): method_url = r'setChatMenuButton' payload = {} From 1d62adc26261da555c2c2b6e7cf9b588c4bec3d2 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 22 Apr 2023 18:30:46 +0400 Subject: [PATCH 006/480] Added the ability to get the current bot name in the given language as the class BotName using the method getMyName. --- telebot/__init__.py | 16 ++++++++++++++++ telebot/apihelper.py | 7 +++++++ telebot/async_telebot.py | 16 ++++++++++++++++ telebot/asyncio_helper.py | 7 +++++++ telebot/types.py | 24 ++++++++++++++++++++++++ 5 files changed, 70 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 549a69de9..c1aaec077 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3462,6 +3462,22 @@ def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=Non return apihelper.set_my_name(self.token, name, language_code) + def get_my_name(self, language_code: Optional[str]=None): + """ + Use this method to get the current bot name for the given user language. + Returns BotName on success. + + Telegram documentation: https://core.telegram.org/bots/api#getmyname + + :param language_code: Optional. A two-letter ISO 639-1 language code or an empty string + :type language_code: :obj:`str` + + :return: :class:`telebot.types.BotName` + """ + + result = apihelper.get_my_name(self.token, language_code) + return types.BotName.de_json(result) + def set_my_description(self, description: Optional[str]=None, language_code: Optional[str]=None): """ Use this method to change the bot's description, which is shown in diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 8d2b1e72e..57102f900 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1205,6 +1205,13 @@ def set_my_name(token, name=None, language_code=None): payload['language_code'] = language_code return _make_request(token, method_url, params=payload, method='post') +def get_my_name(token, language_code=None): + method_url = r'getMyName' + payload = {} + if language_code is not None: + payload['language_code'] = language_code + return _make_request(token, method_url, params=payload) + def set_chat_menu_button(token, chat_id=None, menu_button=None): method_url = r'setChatMenuButton' payload = {} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 242e74c4b..a9d2ac872 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4379,6 +4379,22 @@ async def set_my_name(self, name: Optional[str]=None, language_code: Optional[st return await asyncio_helper.set_my_name(self.token, name, language_code) + async def get_my_name(self, language_code: Optional[str]=None): + """ + Use this method to get the current bot name for the given user language. + Returns BotName on success. + + Telegram documentation: https://core.telegram.org/bots/api#getmyname + + :param language_code: Optional. A two-letter ISO 639-1 language code or an empty string + :type language_code: :obj:`str` + + :return: :class:`telebot.types.BotName` + """ + + result = await asyncio_helper.get_my_name(self.token, language_code) + return types.BotName.de_json(result) + async def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 804e51654..507aec020 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1193,6 +1193,13 @@ async def set_my_name(token, name=None, language_code=None): payload['language_code'] = language_code return await _process_request(token, method_url, params=payload, method='post') +async def get_my_name(token, language_code=None): + method_url = r'getMyName' + payload = {} + if language_code is not None: + payload['language_code'] = language_code + return await _process_request(token, method_url, params=payload) + async def set_chat_menu_button(token, chat_id=None, menu_button=None): method_url = r'setChatMenuButton' payload = {} diff --git a/telebot/types.py b/telebot/types.py index 53b692d65..8a4460ee3 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7658,3 +7658,27 @@ def to_dict(self): def to_json(self): return json.dumps(self.to_dict()) + + +class BotName(JsonDeserializable): + """ + This object represents a bot name. + + Telegram Documentation: https://core.telegram.org/bots/api#botname + + :param name: The bot name + :type name: :obj:`str` + + :return: Instance of the class + :rtype: :class:`BotName` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, name: str): + self.name: str = name \ No newline at end of file From be69feb25284f0d7dba3d7e6a8d96c55e72ae0de Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 22 Apr 2023 20:38:05 +0400 Subject: [PATCH 007/480] * Added a test for message entity __html_text function. #1971 should be fixed and then todo can be done. --- tests/test_types.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/test_types.py b/tests/test_types.py index c696f162c..8c15396c9 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -271,5 +271,30 @@ def test_sent_web_app_message(): assert sent_web_app_message.inline_message_id == '29430' +def test_message_entity(): + # TODO: Add support for nesting entities + + + #sample_string_1 = r'{"update_id":934522126,"message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682177590,"text":"b b b","entities":[{"offset":0,"length":2,"type":"bold"},{"offset":0,"length":1,"type":"italic"},{"offset":2,"length":2,"type":"bold"},{"offset":2,"length":1,"type":"italic"},{"offset":4,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}' + #update = types.Update.de_json(sample_string_1) + #message: types.Message = update.message + #assert message.html_text == "b b b" + + sample_string_2 = r'{"update_id":934522166,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"text":"b b b","entities":[{"offset":0,"length":1,"type":"bold"},{"offset":2,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}' + message_2 = types.Update.de_json(sample_string_2).message + assert message_2.html_text == "b b b" + + + + #sample_string_3 = r'{"update_id":934522172,"message":{"message_id":1374530,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179968,"text":"This is a bold text with a nested italic and bold text.","entities":[{"offset":10,"length":4,"type":"bold"},{"offset":27,"length":7,"type":"italic"},{"offset":34,"length":15,"type":"bold"},{"offset":34,"length":15,"type":"italic"}]}}' + #message_3 = types.Update.de_json(sample_string_3).message + #assert message_3.html_text == "This is a bold text with a nested italic and bold text." + + + assert True + + + + From 26575dc5e7f25f026f03371243babca7022ca5cb Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 22 Apr 2023 20:51:08 +0400 Subject: [PATCH 008/480] Added support for launching Web Apps from inline query results by replacing the parameters switch_pm_text and switch_pm_parameter of the method answerInlineQuery with the parameter button of type InlineQueryResultsButton. --- telebot/__init__.py | 12 +++++++-- telebot/apihelper.py | 8 +++--- telebot/async_telebot.py | 12 +++++++-- telebot/asyncio_helper.py | 10 ++++---- telebot/types.py | 51 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 78 insertions(+), 15 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index c1aaec077..0579325c3 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4521,7 +4521,8 @@ def answer_inline_query( is_personal: Optional[bool]=None, next_offset: Optional[str]=None, switch_pm_text: Optional[str]=None, - switch_pm_parameter: Optional[str]=None) -> bool: + switch_pm_parameter: Optional[str]=None, + button: Optional[types.InlineQueryResultsButton]=None) -> bool: """ Use this method to send answers to an inline query. On success, True is returned. No more than 50 results per query are allowed. @@ -4557,11 +4558,18 @@ def answer_inline_query( :param switch_pm_text: Parameter for the start message sent to the bot when user presses the switch button :type switch_pm_text: :obj:`str` + :param button: A JSON-serialized object describing a button to be shown above inline query results + :type button: :obj:`types.InlineQueryResultsButton` + :return: On success, True is returned. :rtype: :obj:`bool` """ + if not button and (switch_pm_text or switch_pm_parameter): + logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.") + button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter) + return apihelper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, - switch_pm_text, switch_pm_parameter) + button) def answer_callback_query( self, callback_query_id: int, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 57102f900..a07f1ef91 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1614,7 +1614,7 @@ def answer_callback_query(token, callback_query_id, text=None, show_alert=None, def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None, - switch_pm_text=None, switch_pm_parameter=None): + button=None): method_url = 'answerInlineQuery' payload = {'inline_query_id': inline_query_id, 'results': _convert_list_json_serializable(results)} if cache_time is not None: @@ -1623,10 +1623,8 @@ def answer_inline_query(token, inline_query_id, results, cache_time=None, is_per payload['is_personal'] = is_personal if next_offset is not None: payload['next_offset'] = next_offset - if switch_pm_text: - payload['switch_pm_text'] = switch_pm_text - if switch_pm_parameter: - payload['switch_pm_parameter'] = switch_pm_parameter + if button is not None: + payload["button"] = button.to_json() return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index a9d2ac872..1a86024d5 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5371,7 +5371,8 @@ async def answer_inline_query( is_personal: Optional[bool]=None, next_offset: Optional[str]=None, switch_pm_text: Optional[str]=None, - switch_pm_parameter: Optional[str]=None) -> bool: + switch_pm_parameter: Optional[str]=None, + button: Optional[types.InlineQueryResultsButton]=None) -> bool: """ Use this method to send answers to an inline query. On success, True is returned. No more than 50 results per query are allowed. @@ -5407,11 +5408,18 @@ async def answer_inline_query( :param switch_pm_text: Parameter for the start message sent to the bot when user presses the switch button :type switch_pm_text: :obj:`str` + :param button: A JSON-serialized object describing a button to be shown above inline query results + :type button: :obj:`types.InlineQueryResultsButton` + :return: On success, True is returned. :rtype: :obj:`bool` """ + + if not button and (switch_pm_text or switch_pm_parameter): + logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.") + button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter) return await asyncio_helper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, - switch_pm_text, switch_pm_parameter) + button) async def answer_callback_query( self, callback_query_id: int, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 507aec020..5a615b397 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1604,7 +1604,7 @@ async def answer_callback_query(token, callback_query_id, text=None, show_alert= async def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None, - switch_pm_text=None, switch_pm_parameter=None): + button=None): method_url = 'answerInlineQuery' payload = {'inline_query_id': inline_query_id, 'results': await _convert_list_json_serializable(results)} if cache_time is not None: @@ -1613,10 +1613,10 @@ async def answer_inline_query(token, inline_query_id, results, cache_time=None, payload['is_personal'] = is_personal if next_offset is not None: payload['next_offset'] = next_offset - if switch_pm_text: - payload['switch_pm_text'] = switch_pm_text - if switch_pm_parameter: - payload['switch_pm_parameter'] = switch_pm_parameter + if button is not None: + payload["button"] = button.to_json() + + return await _process_request(token, method_url, params=payload, method='post') diff --git a/telebot/types.py b/telebot/types.py index 8a4460ee3..9f5a50747 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7681,4 +7681,53 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, name: str): - self.name: str = name \ No newline at end of file + self.name: str = name + + +class InlineQueryResultsButton(JsonSerializable, Dictionaryable): + """ + This object represents a button to be shown above inline query results. + You must use exactly one of the optional fields. + + Telegram documentation: https://core.telegram.org/bots/api#inlinequeryresultsbutton + + :param text: Label text on the button + :type text: :obj:`str` + + :param web_app: Optional. Description of the Web App that will be launched when the user presses the button. + The Web App will be able to switch back to the inline mode using the method web_app_switch_inline_query inside the Web App. + :type web_app: :class:`telebot.types.WebAppInfo` + + :param start_parameter: Optional. Deep-linking parameter for the /start message sent to the bot when a user presses the button. + 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed. + Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube account to adapt search + results accordingly. To do this, it displays a 'Connect your YouTube account' button above the results, or even before showing + any. The user presses the button, switches to a private chat with the bot and, in doing so, passes a start parameter that instructs + the bot to return an OAuth link. Once done, the bot can offer a switch_inline button so that the user can easily return to the chat + where they wanted to use the bot's inline capabilities. + :type start_parameter: :obj:`str` + + :return: Instance of the class + :rtype: :class:`InlineQueryResultsButton` + """ + + def __init__(self, text: str, web_app: Optional[WebAppInfo]=None, start_parameter: Optional[str]=None) -> None: + self.text: str = text + self.web_app: Optional[WebAppInfo] = web_app + self.start_parameter: Optional[str] = start_parameter + + + def to_dict(self) -> dict: + json_dict = { + 'text': self.text + } + + if self.web_app is not None: + json_dict['web_app'] = self.web_app.to_dict() + if self.start_parameter is not None: + json_dict['start_parameter'] = self.start_parameter + + return json_dict + + def to_json(self) -> str: + return json.dumps(self.to_dict()) \ No newline at end of file From ecb5d9b4f68c315f53843b5f3900a314245b799a Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 22 Apr 2023 22:53:57 +0400 Subject: [PATCH 009/480] Added tests for __html_text, fixed the bug, added custom_emoji for entities --- telebot/types.py | 32 ++++++++++++++++++++++---------- tests/test_types.py | 19 +++++++++++-------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 9f5a50747..b793073fd 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1313,6 +1313,7 @@ def __html_text(self, text, entities): "strikethrough": "{text}", "underline": "{text}", "spoiler": "{text}", + "custom_emoji": "{text}" } if hasattr(self, "custom_subs"): @@ -1321,7 +1322,7 @@ def __html_text(self, text, entities): utf16_text = text.encode("utf-16-le") html_text = "" - def func(upd_text, subst_type=None, url=None, user=None): + def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): upd_text = upd_text.decode("utf-16-le") if subst_type == "text_mention": subst_type = "text_link" @@ -1332,30 +1333,41 @@ def func(upd_text, subst_type=None, url=None, user=None): if not subst_type or not _subs.get(subst_type): return upd_text subs = _subs.get(subst_type) + if subst_type == "custom_emoji": + return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) return subs.format(text=upd_text, url=url) offset = 0 + start_index = 0 + end_index = 0 for entity in entities: if entity.offset > offset: + # when the offset is not 0: for example, a __b__ + # we need to add the text before the entity to the html_text html_text += func(utf16_text[offset * 2 : entity.offset * 2]) offset = entity.offset - html_text += func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user) + + new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user, entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string offset += entity.length + end_index = len(html_text) elif entity.offset == offset: - html_text += func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user) + new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user, entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + end_index = len(html_text) offset += entity.length else: # Here we are processing nested entities. # We shouldn't update offset, because they are the same as entity before. # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, # And we don't change it). - entity_string = utf16_text[entity.offset * 2 : (entity.offset + entity.length) * 2] - formatted_string = func(entity_string, entity.type, entity.url, entity.user) - entity_string_decoded = entity_string.decode("utf-16-le") - last_occurence = html_text.rfind(entity_string_decoded) - string_length = len(entity_string_decoded) - #html_text = html_text.replace(html_text[last_occurence:last_occurence+string_length], formatted_string) - html_text = html_text[:last_occurence] + formatted_string + html_text[last_occurence+string_length:] + entity_string = html_text[start_index : end_index].encode("utf-16-le") + formatted_string = func(entity_string, entity.type, entity.url, entity.user, entity.custom_emoji_id).replace("&", "&").replace("<", "<").replace(">",">") + html_text = html_text[:start_index] + formatted_string + html_text[end_index:] + end_index = len(html_text) + if offset * 2 < len(utf16_text): html_text += func(utf16_text[offset * 2:]) diff --git a/tests/test_types.py b/tests/test_types.py index 8c15396c9..138c36b8c 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -275,10 +275,10 @@ def test_message_entity(): # TODO: Add support for nesting entities - #sample_string_1 = r'{"update_id":934522126,"message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682177590,"text":"b b b","entities":[{"offset":0,"length":2,"type":"bold"},{"offset":0,"length":1,"type":"italic"},{"offset":2,"length":2,"type":"bold"},{"offset":2,"length":1,"type":"italic"},{"offset":4,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}' - #update = types.Update.de_json(sample_string_1) - #message: types.Message = update.message - #assert message.html_text == "b b b" + sample_string_1 = r'{"update_id":934522126,"message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682177590,"text":"b b b","entities":[{"offset":0,"length":2,"type":"bold"},{"offset":0,"length":1,"type":"italic"},{"offset":2,"length":2,"type":"bold"},{"offset":2,"length":1,"type":"italic"},{"offset":4,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}' + update = types.Update.de_json(sample_string_1) + message: types.Message = update.message + assert message.html_text == "b b b" sample_string_2 = r'{"update_id":934522166,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"text":"b b b","entities":[{"offset":0,"length":1,"type":"bold"},{"offset":2,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}' message_2 = types.Update.de_json(sample_string_2).message @@ -286,12 +286,15 @@ def test_message_entity(): - #sample_string_3 = r'{"update_id":934522172,"message":{"message_id":1374530,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179968,"text":"This is a bold text with a nested italic and bold text.","entities":[{"offset":10,"length":4,"type":"bold"},{"offset":27,"length":7,"type":"italic"},{"offset":34,"length":15,"type":"bold"},{"offset":34,"length":15,"type":"italic"}]}}' - #message_3 = types.Update.de_json(sample_string_3).message - #assert message_3.html_text == "This is a bold text with a nested italic and bold text." + sample_string_3 = r'{"update_id":934522172,"message":{"message_id":1374530,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179968,"text":"This is a bold text with a nested italic and bold text.","entities":[{"offset":10,"length":4,"type":"bold"},{"offset":27,"length":7,"type":"italic"},{"offset":34,"length":15,"type":"bold"},{"offset":34,"length":15,"type":"italic"}]}}' + message_3 = types.Update.de_json(sample_string_3).message + assert message_3.html_text == "This is a bold text with a nested italic and bold text." - assert True + sample_string_4 = r'{"update_id":934522437,"message":{"message_id":1374619,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682189507,"forward_from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"forward_date":1682189124,"text":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa😋😋","entities":[{"offset":0,"length":76,"type":"bold"},{"offset":0,"length":76,"type":"italic"},{"offset":0,"length":76,"type":"underline"},{"offset":0,"length":76,"type":"strikethrough"},{"offset":76,"length":2,"type":"custom_emoji","custom_emoji_id":"5456188142006575553"},{"offset":78,"length":2,"type":"custom_emoji","custom_emoji_id":"5456188142006575553"}]}}' + message_4 = types.Update.de_json(sample_string_4).message + assert message_4.html_text == 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa😋😋' + From 58d53e1a54470513004fc1927801d7cdb1c6dd1a Mon Sep 17 00:00:00 2001 From: AmirW Date: Fri, 28 Apr 2023 16:12:23 +0330 Subject: [PATCH 010/480] bring back the async func message_filter -fixes #1974 - related commits: c84896391eac80eb08b17d0636999499e921723e f69a2ba044983fbd7b072946df7512d0e2904cd6 --- telebot/async_telebot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 1a86024d5..72e7ad4c0 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -16,7 +16,7 @@ from telebot.asyncio_storage import StateMemoryStorage, StatePickleStorage, StateStorageBase from telebot.asyncio_handler_backends import BaseMiddleware, CancelUpdate, SkipHandler, State, ContinueHandling -from inspect import signature +from inspect import signature, iscoroutinefunction from telebot import util, types, asyncio_helper import asyncio @@ -836,6 +836,8 @@ async def _test_filter(self, message_filter, filter_value, message): elif message_filter == 'chat_types': return message.chat.type in filter_value elif message_filter == 'func': + if iscoroutinefunction(filter_value): + return await filter_value(message) return filter_value(message) elif self.custom_filters and message_filter in self.custom_filters: return await self._check_filter(message_filter,filter_value,message) From 14294d1aa33487a780eb7085ead63d1b07a44119 Mon Sep 17 00:00:00 2001 From: Alexey Isaev Date: Sat, 18 Mar 2023 14:43:23 +0300 Subject: [PATCH 011/480] redesigned the antiflood method for guaranteed message delivery --- telebot/util.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/telebot/util.py b/telebot/util.py index 405daf57e..3e9dc5c60 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -588,7 +588,7 @@ def webhook_google_functions(bot, request): return 'Bot ON' -def antiflood(function: Callable, *args, **kwargs): +def antiflood(function: Callable, *args, number_retries=5, **kwargs): """ Use this function inside loops in order to avoid getting TooManyRequests error. Example: @@ -602,6 +602,9 @@ def antiflood(function: Callable, *args, **kwargs): :param function: The function to call :type function: :obj:`Callable` + :param number_retries: Number of retries to send + :type function: :obj:int + :param args: The arguments to pass to the function :type args: :obj:`tuple` @@ -613,14 +616,16 @@ def antiflood(function: Callable, *args, **kwargs): from telebot.apihelper import ApiTelegramException from time import sleep - try: - return function(*args, **kwargs) - except ApiTelegramException as ex: - if ex.error_code == 429: - sleep(ex.result_json['parameters']['retry_after']) + for _ in range(number_retries - 1): + try: return function(*args, **kwargs) - else: - raise + except ApiTelegramException as ex: + if ex.error_code == 429: + sleep(ex.result_json['parameters']['retry_after']) + else: + raise + else: + return function(*args, **kwargs) def parse_web_app_data(token: str, raw_init_data: str): From 2dac17aa758c9f29836cee21c653f2bcfa3f6317 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 18 May 2023 18:07:09 +0300 Subject: [PATCH 012/480] Bump version to 4.12.0 --- docs/source/conf.py | 4 ++-- telebot/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 62ffd29df..f698fc698 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,11 +18,11 @@ # -- Project information ----------------------------------------------------- project = 'pyTelegramBotAPI Documentation' -copyright = '2022, coder2020official' +copyright = '2022-2023, coder2020official' author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.11.0' +release = '4.12.0' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index 6624f64e3..b42b55928 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.11.0' +__version__ = '4.12.0' From eaf90cce7f7e0ca9ef0f76ac156c7094f6e7bfb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 21:33:40 +0000 Subject: [PATCH 013/480] Bump requests from 2.20.0 to 2.31.0 Bumps [requests](https://github.com/psf/requests) from 2.20.0 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.20.0...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 516882869..fdbff1c63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest -requests==2.20.0 +requests==2.31.0 wheel==0.38.1 aiohttp>=3.8.0,<3.9.0 \ No newline at end of file From 5ea1abaadd5d92a917f83c903eb99e6b0c7637ee Mon Sep 17 00:00:00 2001 From: Artem Lukin <48987557+artemetra@users.noreply.github.com> Date: Sun, 18 Jun 2023 01:57:08 +0200 Subject: [PATCH 014/480] fix typo in docs --- telebot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 0579325c3..77cdd0ded 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6598,7 +6598,7 @@ def register_chat_member_handler(self, callback: Callable, func: Optional[Callab Registers chat member handler. :param callback: function to be called - :type callback: :obj:`function`` + :type callback: :obj:`function` :param func: Function executed as a filter :type func: :obj:`function` From fb98df3dfe47432e8fc1824a60cf9737445f08f8 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 8 Jul 2023 22:57:13 +0500 Subject: [PATCH 015/480] Fixed deprecation warning for readthedocs.org --- .readthedocs.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..ac48ea5a0 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,22 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.9" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: docs/requirements.txt From af3a98057f90e0920adea593bc7926a8a8403ac6 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 8 Jul 2023 23:10:41 +0500 Subject: [PATCH 016/480] Updated all russian docstrings, currently without translation. --- .../locales/en/LC_MESSAGES/async_version.po | 527 ++++- .../locales/en/LC_MESSAGES/sync_version.po | 699 ++++++- docs/source/locales/en/LC_MESSAGES/types.po | 739 +++++-- docs/source/locales/en/LC_MESSAGES/util.po | 90 +- .../locales/ru/LC_MESSAGES/async_version.po | 1529 +++++++++----- .../locales/ru/LC_MESSAGES/sync_version.po | 1781 +++++++++++------ docs/source/locales/ru/LC_MESSAGES/types.po | 739 +++++-- docs/source/locales/ru/LC_MESSAGES/util.po | 161 +- 8 files changed, 4558 insertions(+), 1707 deletions(-) diff --git a/docs/source/locales/en/LC_MESSAGES/async_version.po b/docs/source/locales/en/LC_MESSAGES/async_version.po index 083d1096f..cce40349e 100644 --- a/docs/source/locales/en/LC_MESSAGES/async_version.po +++ b/docs/source/locales/en/LC_MESSAGES/async_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-02 19:24+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -105,6 +105,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_webhook #: telebot.async_telebot.AsyncTeleBot.download_file #: telebot.async_telebot.AsyncTeleBot.edit_chat_invite_link @@ -131,6 +132,9 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_game_high_scores #: telebot.async_telebot.AsyncTeleBot.get_my_commands #: telebot.async_telebot.AsyncTeleBot.get_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.get_my_description +#: telebot.async_telebot.AsyncTeleBot.get_my_name +#: telebot.async_telebot.AsyncTeleBot.get_my_short_description #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates @@ -196,12 +200,20 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_photo #: telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.set_chat_title +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.set_my_description +#: telebot.async_telebot.AsyncTeleBot.set_my_name +#: telebot.async_telebot.AsyncTeleBot.set_my_short_description #: telebot.async_telebot.AsyncTeleBot.set_state +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title #: telebot.async_telebot.AsyncTeleBot.set_update_listener #: telebot.async_telebot.AsyncTeleBot.set_webhook #: telebot.async_telebot.AsyncTeleBot.setup_middleware @@ -304,6 +316,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_webhook #: telebot.async_telebot.AsyncTeleBot.download_file #: telebot.async_telebot.AsyncTeleBot.edit_chat_invite_link @@ -329,6 +342,9 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_game_high_scores #: telebot.async_telebot.AsyncTeleBot.get_my_commands #: telebot.async_telebot.AsyncTeleBot.get_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.get_my_description +#: telebot.async_telebot.AsyncTeleBot.get_my_name +#: telebot.async_telebot.AsyncTeleBot.get_my_short_description #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates @@ -392,12 +408,20 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_photo #: telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.set_chat_title +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.set_my_description +#: telebot.async_telebot.AsyncTeleBot.set_my_name +#: telebot.async_telebot.AsyncTeleBot.set_my_short_description #: telebot.async_telebot.AsyncTeleBot.set_state +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title #: telebot.async_telebot.AsyncTeleBot.set_update_listener #: telebot.async_telebot.AsyncTeleBot.set_webhook #: telebot.async_telebot.AsyncTeleBot.setup_middleware @@ -477,32 +501,45 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:1 msgid "" -"Use this method to add a new sticker to a set created by the bot. It's " -"required to pass `png_sticker` or `tgs_sticker`. Returns True on success." +"Use this method to add a new sticker to a set created by the bot. The " +"format of the added sticker must match the format of the other stickers " +"in the set. Emoji sticker sets can have up to 200 stickers. Animated and " +"video sticker sets can have up to 50 stickers. Static sticker sets can " +"have up to 120 stickers. Returns True on success." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:5 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:8 +msgid "" +"**_sticker, mask_position, emojis parameters are deprecated, use stickers" +" instead" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:10 msgid "Telegram documentation: https://core.telegram.org/bots/api#addstickertoset" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:7 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:7 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:12 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:10 msgid "User identifier of created sticker set owner" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:10 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:15 +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:3 #: telebot.async_telebot.AsyncTeleBot.get_sticker_set:5 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:6 +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:4 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:4 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:6 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:4 msgid "Sticker set name" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:13 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:18 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:18 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:21 msgid "One or more emoji corresponding to the sticker" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:16 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:21 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:21 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:24 msgid "" "PNG image with the sticker, must be up to 512 kilobytes in size, " "dimensions must not exceed 512px, and either width or height must be " @@ -512,36 +549,43 @@ msgid "" "/form-data." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:21 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:26 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:26 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:29 msgid "TGS animation with the sticker, uploaded using multipart/form-data." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:24 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:29 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:29 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:32 msgid "WebM animation with the sticker, uploaded using multipart/form-data." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:27 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:40 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:32 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:42 msgid "" "A JSON-serialized object for position where the mask should be placed on " "faces" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:30 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:35 +msgid "" +"A JSON-serialized list of 1-50 initial stickers to be added to the " +"sticker set" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:38 #: telebot.async_telebot.AsyncTeleBot.answer_callback_query:22 -#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:35 +#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:38 #: telebot.async_telebot.AsyncTeleBot.answer_pre_checkout_query:21 #: telebot.async_telebot.AsyncTeleBot.answer_shipping_query:18 #: telebot.async_telebot.AsyncTeleBot.close_forum_topic:13 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:43 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:56 #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic:13 #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set:6 #: telebot.async_telebot.AsyncTeleBot.edit_forum_topic:22 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:13 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:11 #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:11 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:15 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:13 msgid "On success, True is returned." msgstr "" @@ -568,6 +612,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_message #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_webhook #: telebot.async_telebot.AsyncTeleBot.download_file #: telebot.async_telebot.AsyncTeleBot.edit_chat_invite_link @@ -627,11 +672,16 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_photo #: telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.set_chat_title +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title #: telebot.async_telebot.AsyncTeleBot.set_webhook #: telebot.async_telebot.AsyncTeleBot.stop_message_live_location #: telebot.async_telebot.AsyncTeleBot.stop_poll @@ -644,9 +694,9 @@ msgstr "" msgid "Return type" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:31 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:39 #: telebot.async_telebot.AsyncTeleBot.answer_callback_query:23 -#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:36 +#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:39 #: telebot.async_telebot.AsyncTeleBot.answer_pre_checkout_query:22 #: telebot.async_telebot.AsyncTeleBot.answer_shipping_query:19 #: telebot.async_telebot.AsyncTeleBot.approve_chat_join_request:15 @@ -654,7 +704,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat:17 #: telebot.async_telebot.AsyncTeleBot.close:9 #: telebot.async_telebot.AsyncTeleBot.close_forum_topic:14 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:44 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:57 #: telebot.async_telebot.AsyncTeleBot.decline_chat_join_request:15 #: telebot.async_telebot.AsyncTeleBot.delete_chat_photo:13 #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set:11 @@ -662,6 +712,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_message:23 #: telebot.async_telebot.AsyncTeleBot.delete_my_commands:17 #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set:7 +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:7 #: telebot.async_telebot.AsyncTeleBot.delete_webhook:13 #: telebot.async_telebot.AsyncTeleBot.edit_forum_topic:23 #: telebot.async_telebot.AsyncTeleBot.leave_chat:8 @@ -669,18 +720,23 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:19 #: telebot.async_telebot.AsyncTeleBot.promote_chat_member:61 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:14 -#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:48 +#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:61 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:26 #: telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:18 #: telebot.async_telebot.AsyncTeleBot.set_chat_description:14 #: telebot.async_telebot.AsyncTeleBot.set_chat_menu_button:15 -#: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:15 +#: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:21 #: telebot.async_telebot.AsyncTeleBot.set_chat_photo:16 #: telebot.async_telebot.AsyncTeleBot.set_chat_title:17 +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:11 #: telebot.async_telebot.AsyncTeleBot.set_my_commands:18 #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:18 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:11 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:12 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:12 #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:12 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:16 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:16 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:11 #: telebot.async_telebot.AsyncTeleBot.unban_chat_member:20 #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:12 @@ -795,6 +851,12 @@ msgid "" "switch button" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.answer_inline_query:35 +msgid "" +"A JSON-serialized object describing a button to be shown above inline " +"query results" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.answer_pre_checkout_query:1 msgid "" "Once the user has confirmed their payment and shipping details, the Bot " @@ -920,7 +982,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_chat_member:8 #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:6 #: telebot.async_telebot.AsyncTeleBot.promote_chat_member:11 -#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:11 +#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:14 #: telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:10 #: telebot.async_telebot.AsyncTeleBot.unban_chat_member:13 msgid "Unique identifier of the target user" @@ -941,6 +1003,9 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_title:16 #: telebot.async_telebot.AsyncTeleBot.set_my_commands:17 #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:17 +#: telebot.async_telebot.AsyncTeleBot.set_my_description:12 +#: telebot.async_telebot.AsyncTeleBot.set_my_name:12 +#: telebot.async_telebot.AsyncTeleBot.set_my_short_description:12 #: telebot.async_telebot.AsyncTeleBot.set_webhook:46 #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:14 #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:11 @@ -961,7 +1026,7 @@ msgid "Telegram documentation: https://core.telegram.org/bots/api#banchatmember" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.ban_chat_member:8 -#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:7 +#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:10 msgid "" "Unique identifier for the target group or username of the target " "supergroup or channel (in the format @channelusername)" @@ -985,8 +1050,13 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.ban_chat_member:24 #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set:10 #: telebot.async_telebot.AsyncTeleBot.delete_message:22 +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:6 #: telebot.async_telebot.AsyncTeleBot.delete_webhook:12 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:25 +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:10 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:10 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:11 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:10 msgid "Returns True on success." msgstr "" @@ -1394,21 +1464,21 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.copy_message:45 #: telebot.async_telebot.AsyncTeleBot.forward_message:26 #: telebot.async_telebot.AsyncTeleBot.reply_to:11 -#: telebot.async_telebot.AsyncTeleBot.send_animation:63 -#: telebot.async_telebot.AsyncTeleBot.send_audio:63 +#: telebot.async_telebot.AsyncTeleBot.send_animation:66 +#: telebot.async_telebot.AsyncTeleBot.send_audio:66 #: telebot.async_telebot.AsyncTeleBot.send_contact:44 #: telebot.async_telebot.AsyncTeleBot.send_dice:35 -#: telebot.async_telebot.AsyncTeleBot.send_document:56 +#: telebot.async_telebot.AsyncTeleBot.send_document:59 #: telebot.async_telebot.AsyncTeleBot.send_game:32 #: telebot.async_telebot.AsyncTeleBot.send_invoice:101 #: telebot.async_telebot.AsyncTeleBot.send_location:49 #: telebot.async_telebot.AsyncTeleBot.send_message:46 #: telebot.async_telebot.AsyncTeleBot.send_photo:48 #: telebot.async_telebot.AsyncTeleBot.send_poll:70 -#: telebot.async_telebot.AsyncTeleBot.send_sticker:39 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:42 #: telebot.async_telebot.AsyncTeleBot.send_venue:57 -#: telebot.async_telebot.AsyncTeleBot.send_video:64 -#: telebot.async_telebot.AsyncTeleBot.send_video_note:48 +#: telebot.async_telebot.AsyncTeleBot.send_video:67 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:51 #: telebot.async_telebot.AsyncTeleBot.send_voice:49 msgid "On success, the sent Message is returned." msgstr "" @@ -1416,18 +1486,18 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.copy_message:46 #: telebot.async_telebot.AsyncTeleBot.forward_message:27 #: telebot.async_telebot.AsyncTeleBot.reply_to:12 -#: telebot.async_telebot.AsyncTeleBot.send_animation:64 -#: telebot.async_telebot.AsyncTeleBot.send_audio:64 +#: telebot.async_telebot.AsyncTeleBot.send_animation:67 +#: telebot.async_telebot.AsyncTeleBot.send_audio:67 #: telebot.async_telebot.AsyncTeleBot.send_contact:45 #: telebot.async_telebot.AsyncTeleBot.send_dice:36 -#: telebot.async_telebot.AsyncTeleBot.send_document:57 +#: telebot.async_telebot.AsyncTeleBot.send_document:60 #: telebot.async_telebot.AsyncTeleBot.send_location:50 #: telebot.async_telebot.AsyncTeleBot.send_message:47 #: telebot.async_telebot.AsyncTeleBot.send_photo:49 -#: telebot.async_telebot.AsyncTeleBot.send_sticker:40 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:43 #: telebot.async_telebot.AsyncTeleBot.send_venue:58 -#: telebot.async_telebot.AsyncTeleBot.send_video:65 -#: telebot.async_telebot.AsyncTeleBot.send_video_note:49 +#: telebot.async_telebot.AsyncTeleBot.send_video:68 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:52 msgid ":class:`telebot.types.Message`" msgstr "" @@ -1680,7 +1750,13 @@ msgid "" "https://core.telegram.org/bots/api#createnewstickerset" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:10 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:8 +msgid "" +"Fields *_sticker are deprecated, pass a list of stickers to stickers " +"parameter instead." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:13 msgid "" "Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., " "animals). Can contain only English letters, digits and underscores. Must " @@ -1689,21 +1765,38 @@ msgid "" "characters." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:15 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:18 msgid "Sticker set title, 1-64 characters" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:32 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:35 msgid "" "Pass True, if a set of mask stickers should be created. Deprecated since " "Bot API 6.2, use sticker_type instead." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:36 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:39 msgid "" -"Optional, Type of stickers in the set, pass “regular” or “mask”. Custom " -"emoji sticker sets can't be created via the Bot API at the moment. By " -"default, a regular sticker set is created." +"Type of stickers in the set, pass “regular”, “mask”, or “custom_emoji”. " +"By default, a regular sticker set is created." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:45 +msgid "" +"Pass True if stickers in the sticker set must be repainted to the color " +"of text when used in messages, the accent color if used as emoji status, " +"white on chat photos, or another appropriate color based on context; for " +"custom emoji sticker sets only" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:50 +msgid "List of stickers to be added to the set" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:53 +msgid "" +"Format of stickers in the set, must be one of “static”, “animated”, " +"“video”" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.decline_chat_join_request:1 @@ -1846,6 +1939,10 @@ msgstr "" msgid "File identifier of the sticker" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.delete_sticker_set:1 +msgid "Use this method to delete a sticker set. Returns True on success." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.delete_webhook:1 msgid "" "Use this method to remove webhook integration if you decide to switch " @@ -2396,7 +2493,7 @@ msgid "File identifier" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.get_file:12 -#: telebot.async_telebot.AsyncTeleBot.upload_sticker_file:14 +#: telebot.async_telebot.AsyncTeleBot.upload_sticker_file:21 msgid ":class:`telebot.types.File`" msgstr "" @@ -2457,7 +2554,7 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.get_game_high_scores:10 #: telebot.async_telebot.AsyncTeleBot.retrieve_data:3 #: telebot.async_telebot.AsyncTeleBot.set_game_score:5 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:9 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:9 msgid "User identifier" msgstr "" @@ -2518,6 +2615,49 @@ msgstr "" msgid ":class:`telebot.types.ChatAdministratorRights`" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.get_my_description:1 +msgid "" +"Use this method to get the current bot description for the given user " +"language. Returns BotDescription on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_description:4 +#: telebot.async_telebot.AsyncTeleBot.get_my_short_description:4 +msgid "A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_description:7 +msgid ":class:`telebot.types.BotDescription`" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:1 +msgid "" +"Use this method to get the current bot name for the given user language. " +"Returns BotName on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#getmyname" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:6 +msgid "Optional. A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:9 +msgid ":class:`telebot.types.BotName`" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_short_description:1 +msgid "" +"Use this method to get the current bot short description for the given " +"user language. Returns BotShortDescription on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_short_description:7 +msgid ":class:`telebot.types.BotShortDescription`" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.get_state:1 msgid "" "Gets current state of a user. Not recommended to use this method. But it " @@ -2589,7 +2729,7 @@ msgid "Array of string. List the types of updates you want your bot to receive." msgstr "" #: of telebot.async_telebot.AsyncTeleBot.get_updates:21 -msgid "Timeout in seconds for long polling." +msgid "Timeout in seconds for request." msgstr "" #: of telebot.async_telebot.AsyncTeleBot.get_updates:24 @@ -3178,61 +3318,85 @@ msgid "" "https://core.telegram.org/bots/api#restrictchatmember" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:14 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:8 +msgid "" +"Individual parameters are deprecated and will be removed, use " +"'permissions' instead" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:17 msgid "" "Date when restrictions will be lifted for the user, unix time. If user is" " restricted for more than 366 days or less than 30 seconds from the " "current time, they are considered to be restricted forever" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:19 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:22 msgid "" "Pass True, if the user can send text messages, contacts, locations and " "venues" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:22 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:25 msgid "" "Pass True, if the user can send audios, documents, photos, videos, video " "notes and voice notes, implies can_send_messages" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:26 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:29 msgid "Pass True, if the user is allowed to send polls, implies can_send_messages" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:29 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:32 msgid "" "Pass True, if the user can send animations, games, stickers and use " "inline bots, implies can_send_media_messages" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:32 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:35 msgid "" "Pass True, if the user may add web page previews to their messages, " "implies can_send_media_messages" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:36 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:39 msgid "" "Pass True, if the user is allowed to change the chat title, photo and " "other settings. Ignored in public supergroups" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:40 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:43 msgid "" "Pass True, if the user is allowed to invite new users to the chat, " "implies can_invite_users" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:44 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:47 msgid "" "Pass True, if the user is allowed to pin messages. Ignored in public " "supergroups" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:47 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:50 #: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:14 +msgid "" +"Pass True if chat permissions are set independently. Otherwise, the " +"can_send_other_messages and can_add_web_page_previews permissions will " +"imply the can_send_messages, can_send_audios, can_send_documents, " +"can_send_photos, can_send_videos, can_send_video_notes, and " +"can_send_voice_notes permissions; the can_send_polls permission will " +"imply the can_send_messages permission." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:56 +msgid "" +"Pass ChatPermissions object to set all permissions at once. Use this " +"parameter instead of passing all boolean parameters to avoid backward " +"compatibility problems in future." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:60 +#: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:20 #: telebot.async_telebot.AsyncTeleBot.unban_chat_member:19 msgid "True on success" msgstr "" @@ -3275,27 +3439,27 @@ msgstr "" msgid "IP address to listen to. Defaults to 0.0.0.0" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:5 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:4 msgid "A port which will be used to listen to webhooks." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:6 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:5 msgid "Path to the webhook. Defaults to /token" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:7 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:6 msgid "Path to the certificate file." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:8 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:7 msgid "Path to the certificate key file." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:9 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:8 msgid "Webhook URL." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:10 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:9 msgid "" "Maximum allowed number of simultaneous HTTPS connections to the webhook " "for update delivery, 1-100. Defaults to 40. Use lower values to limit the" @@ -3303,7 +3467,7 @@ msgid "" "throughput." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:11 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:10 msgid "" "A JSON-serialized list of the update types you want your bot to receive. " "For example, specify [“message”, “edited_channel_post”, “callback_query”]" @@ -3313,24 +3477,32 @@ msgid "" " be used." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:12 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:11 msgid "" "The fixed IP address which will be used to send webhook requests instead " "of the IP address resolved through DNS" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:13 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:12 msgid "Pass True to drop all pending updates" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:14 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:13 msgid "Integer. Request connection timeout" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:15 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:14 msgid "Secret token to be used to verify the webhook request." msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:15 +msgid "Length of a secret token, defaults to 20" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:16 +msgid "Debug mode, defaults to False" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_animation:1 msgid "" "Use this method to send animation files (GIF or H.264/MPEG-4 AVC video " @@ -3402,6 +3574,14 @@ msgstr "" msgid "Pass True, if the animation should be sent as a spoiler" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.send_animation:63 +#: telebot.async_telebot.AsyncTeleBot.send_audio:63 +#: telebot.async_telebot.AsyncTeleBot.send_document:56 +#: telebot.async_telebot.AsyncTeleBot.send_video:64 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:48 +msgid "Deprecated. Use thumbnail instead" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_audio:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -3953,6 +4133,10 @@ msgstr "" msgid "to disable the notification" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.send_sticker:39 +msgid "Emoji associated with the sticker; only for just uploaded stickers" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_venue:1 msgid "" "Use this method to send information about a venue. On success, the sent " @@ -4243,6 +4427,20 @@ msgstr "" msgid "New chat title, 1-255 characters" msgstr "" +#: of +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:1 +msgid "" +"Use this method to set the thumbnail of a custom emoji sticker set. " +"Returns True on success." +msgstr "" + +#: of +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:7 +msgid "" +"Custom emoji identifier of a sticker from the sticker set; pass an empty " +"string to drop the thumbnail and use the first sticker as the thumbnail." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_game_score:1 msgid "Sets the value of points in the game to a specific user." msgstr "" @@ -4312,6 +4510,65 @@ msgid "" "groups and supergroups will be changed." msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.set_my_description:1 +msgid "" +"Use this method to change the bot's description, which is shown in the " +"chat with the bot if the chat is empty. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_description:5 +msgid "" +"New bot description; 0-512 characters. Pass an empty string to remove the" +" dedicated description for the given language." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_description:8 +msgid "" +"A two-letter ISO 639-1 language code. If empty, the description will be " +"applied to all users for whose language there is no dedicated " +"description." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:1 +msgid "Use this method to change the bot's name. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#setmyname" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:5 +msgid "" +"Optional. New bot name; 0-64 characters. Pass an empty string to remove " +"the dedicated name for the given language." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:8 +msgid "" +"Optional. A two-letter ISO 639-1 language code. If empty, the name will " +"be shown to all users for whose language there is no dedicated name." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_short_description:1 +msgid "" +"Use this method to change the bot's short description, which is shown on " +"the bot's profile page and is sent together with the link when users " +"share the bot. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_short_description:5 +msgid "" +"New short description for the bot; 0-120 characters. Pass an empty string" +" to remove the dedicated short description for the given language." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_short_description:8 +msgid "" +"A two-letter ISO 639-1 language code. If empty, the short description " +"will be applied to all users for whose language there is no dedicated " +"short description." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_state:1 msgid "Sets a new state of a user." msgstr "" @@ -4328,6 +4585,47 @@ msgstr "" msgid "new state. can be string, integer, or :class:`telebot.types.State`" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:1 +msgid "" +"Use this method to set the emoji list of a sticker set. Returns True on " +"success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:7 +msgid "List of emojis" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:1 +msgid "" +"Use this method to change search keywords assigned to a regular or custom" +" emoji sticker. The sticker must belong to a sticker set created by the " +"bot. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:5 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:5 +msgid "File identifier of the sticker." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:8 +msgid "" +"A JSON-serialized list of 0-20 search keywords for the sticker with total" +" length of up to 64 characters" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:1 +msgid "" +"Use this method to change the mask position of a mask sticker. The " +"sticker must belong to a sticker set that was created by the bot. Returns" +" True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:8 +msgid "" +"A JSON-serialized object for position where the mask should be placed on " +"faces." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:1 msgid "" "Use this method to move a sticker in a set created by the bot to a " @@ -4344,19 +4642,47 @@ msgstr "" msgid "New sticker position in the set, zero-based" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:1 +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:1 msgid "" "Use this method to set the thumbnail of a sticker set. Animated " "thumbnails can be set for animated sticker sets only. Returns True on " "success." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:4 +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:4 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#setstickersetthumb" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:12 +msgid "" +"A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in " +"size and have a width and height of exactly 100px, or a .TGS animation " +"with a thumbnail up to 32 kilobytes in size (see " +"https://core.telegram.org/stickers#animated-sticker-requirements for " +"animated sticker technical requirements), or a WEBM video with the " +"thumbnail up to 32 kilobytes in size; see " +"https://core.telegram.org/stickers#video-sticker-requirements for video " +"sticker technical requirements. Pass a file_id as a String to send a file" +" that already exists on the Telegram servers, pass an HTTP URL as a " +"String for Telegram to get a file from the Internet, or upload a new one " +"using multipart/form-data. More information on Sending Files ». Animated " +"and video sticker set thumbnails can't be uploaded via HTTP URL. If " +"omitted, then the thumbnail is dropped and the first sticker is used as " +"the thumbnail." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:1 +msgid "" +"Use this method to set the title of a created sticker set. Returns True " +"on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:7 +msgid "New sticker set title" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_update_listener:1 msgid "Update listener is a function that gets any update." msgstr "" @@ -4662,12 +4988,23 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:9 msgid "" -"PNG image with the sticker, must be up to 512 kilobytes in size, " -"dimensions must not exceed 512px, and either width or height must be " -"exactly 512px." +"DEPRECATED: PNG image with the sticker, must be up to 512 kilobytes in " +"size, dimensions must not exceed 512px, and either width or height must " +"be exactly 512px." msgstr "" #: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:13 +msgid "" +"A file with the sticker in .WEBP, .PNG, .TGS, or .WEBM format. See " +"https://core.telegram.org/stickers for technical requirements. More " +"information on Sending Files »" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:17 +msgid "One of \"static\", \"animated\", \"video\"." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:20 msgid "On success, the sent file is returned." msgstr "" @@ -4913,3 +5250,31 @@ msgstr "" #~ "character long" #~ msgstr "" +#~ msgid "" +#~ "Use this method to add a new " +#~ "sticker to a set created by the" +#~ " bot. It's required to pass " +#~ "`png_sticker` or `tgs_sticker`. Returns True" +#~ " on success." +#~ msgstr "" + +#~ msgid "" +#~ "Optional, Type of stickers in the " +#~ "set, pass “regular” or “mask”. Custom" +#~ " emoji sticker sets can't be created" +#~ " via the Bot API at the moment." +#~ " By default, a regular sticker set" +#~ " is created." +#~ msgstr "" + +#~ msgid "Timeout in seconds for long polling." +#~ msgstr "" + +#~ msgid "" +#~ "PNG image with the sticker, must " +#~ "be up to 512 kilobytes in size," +#~ " dimensions must not exceed 512px, " +#~ "and either width or height must be" +#~ " exactly 512px." +#~ msgstr "" + diff --git a/docs/source/locales/en/LC_MESSAGES/sync_version.po b/docs/source/locales/en/LC_MESSAGES/sync_version.po index 766e23cb1..13aa6b3cf 100644 --- a/docs/source/locales/en/LC_MESSAGES/sync_version.po +++ b/docs/source/locales/en/LC_MESSAGES/sync_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-02 19:24+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -113,9 +113,9 @@ msgstr "" #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands #: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file -#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic -#: telebot.TeleBot.edit_general_forum_topic +#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook +#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link +#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_general_forum_topic #: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup @@ -132,16 +132,17 @@ msgstr "" #: telebot.TeleBot.get_file_url telebot.TeleBot.get_game_high_scores #: telebot.TeleBot.get_my_commands #: telebot.TeleBot.get_my_default_administrator_rights -#: telebot.TeleBot.get_state telebot.TeleBot.get_sticker_set -#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_profile_photos -#: telebot.TeleBot.get_webhook_info telebot.TeleBot.hide_general_forum_topic -#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler -#: telebot.TeleBot.leave_chat telebot.TeleBot.load_next_step_handlers -#: telebot.TeleBot.load_reply_handlers telebot.TeleBot.message_handler -#: telebot.TeleBot.middleware_handler telebot.TeleBot.my_chat_member_handler -#: telebot.TeleBot.pin_chat_message telebot.TeleBot.poll_answer_handler -#: telebot.TeleBot.poll_handler telebot.TeleBot.polling -#: telebot.TeleBot.pre_checkout_query_handler +#: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name +#: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state +#: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates +#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info +#: telebot.TeleBot.hide_general_forum_topic telebot.TeleBot.infinity_polling +#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat +#: telebot.TeleBot.load_next_step_handlers telebot.TeleBot.load_reply_handlers +#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message +#: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler +#: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.process_new_updates telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler @@ -174,16 +175,21 @@ msgstr "" #: telebot.TeleBot.send_media_group telebot.TeleBot.send_message #: telebot.TeleBot.send_photo telebot.TeleBot.send_poll #: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note -#: telebot.TeleBot.send_voice +#: telebot.TeleBot.send_video telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights -#: telebot.TeleBot.set_state telebot.TeleBot.set_sticker_position_in_set -#: telebot.TeleBot.set_sticker_set_thumb telebot.TeleBot.set_update_listener +#: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name +#: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state +#: telebot.TeleBot.set_sticker_emoji_list telebot.TeleBot.set_sticker_keywords +#: telebot.TeleBot.set_sticker_mask_position +#: telebot.TeleBot.set_sticker_position_in_set +#: telebot.TeleBot.set_sticker_set_thumbnail +#: telebot.TeleBot.set_sticker_set_title telebot.TeleBot.set_update_listener #: telebot.TeleBot.set_webhook telebot.TeleBot.setup_middleware #: telebot.TeleBot.shipping_query_handler #: telebot.TeleBot.stop_message_live_location telebot.TeleBot.stop_poll @@ -320,9 +326,9 @@ msgstr "" #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands #: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file -#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic -#: telebot.TeleBot.edit_message_caption +#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook +#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link +#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text @@ -337,15 +343,16 @@ msgstr "" #: telebot.TeleBot.get_file_url telebot.TeleBot.get_forum_topic_icon_stickers #: telebot.TeleBot.get_game_high_scores telebot.TeleBot.get_my_commands #: telebot.TeleBot.get_my_default_administrator_rights -#: telebot.TeleBot.get_state telebot.TeleBot.get_sticker_set -#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_profile_photos -#: telebot.TeleBot.get_webhook_info telebot.TeleBot.infinity_polling -#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat -#: telebot.TeleBot.log_out telebot.TeleBot.message_handler -#: telebot.TeleBot.middleware_handler telebot.TeleBot.my_chat_member_handler -#: telebot.TeleBot.pin_chat_message telebot.TeleBot.poll_answer_handler -#: telebot.TeleBot.poll_handler telebot.TeleBot.polling -#: telebot.TeleBot.pre_checkout_query_handler +#: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name +#: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state +#: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates +#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info +#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler +#: telebot.TeleBot.leave_chat telebot.TeleBot.log_out +#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message +#: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler +#: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler @@ -376,16 +383,21 @@ msgstr "" #: telebot.TeleBot.send_media_group telebot.TeleBot.send_message #: telebot.TeleBot.send_photo telebot.TeleBot.send_poll #: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note -#: telebot.TeleBot.send_voice +#: telebot.TeleBot.send_video telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights -#: telebot.TeleBot.set_state telebot.TeleBot.set_sticker_position_in_set -#: telebot.TeleBot.set_sticker_set_thumb telebot.TeleBot.set_webhook +#: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name +#: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state +#: telebot.TeleBot.set_sticker_emoji_list telebot.TeleBot.set_sticker_keywords +#: telebot.TeleBot.set_sticker_mask_position +#: telebot.TeleBot.set_sticker_position_in_set +#: telebot.TeleBot.set_sticker_set_thumbnail +#: telebot.TeleBot.set_sticker_set_title telebot.TeleBot.set_webhook #: telebot.TeleBot.setup_middleware telebot.TeleBot.shipping_query_handler #: telebot.TeleBot.stop_message_live_location telebot.TeleBot.stop_poll #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat @@ -435,31 +447,43 @@ msgstr "" #: of telebot.TeleBot.add_sticker_to_set:1 msgid "" -"Use this method to add a new sticker to a set created by the bot. It's " -"required to pass `png_sticker` or `tgs_sticker`. Returns True on success." +"Use this method to add a new sticker to a set created by the bot. The " +"format of the added sticker must match the format of the other stickers " +"in the set. Emoji sticker sets can have up to 200 stickers. Animated and " +"video sticker sets can have up to 50 stickers. Static sticker sets can " +"have up to 120 stickers. Returns True on success." msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:5 +#: of telebot.TeleBot.add_sticker_to_set:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#addstickertoset" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:7 -#: telebot.TeleBot.create_new_sticker_set:7 +#: of telebot.TeleBot.add_sticker_to_set:10 +msgid "" +"**_sticker, mask_position, emojis parameters are deprecated, use stickers" +" instead" +msgstr "" + +#: of telebot.TeleBot.add_sticker_to_set:12 +#: telebot.TeleBot.create_new_sticker_set:10 msgid "User identifier of created sticker set owner" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:10 telebot.TeleBot.get_sticker_set:5 -#: telebot.TeleBot.set_sticker_set_thumb:6 +#: of telebot.TeleBot.add_sticker_to_set:15 +#: telebot.TeleBot.delete_sticker_set:3 telebot.TeleBot.get_sticker_set:5 +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:4 +#: telebot.TeleBot.set_sticker_set_thumbnail:6 +#: telebot.TeleBot.set_sticker_set_title:4 msgid "Sticker set name" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:13 -#: telebot.TeleBot.create_new_sticker_set:18 +#: of telebot.TeleBot.add_sticker_to_set:18 +#: telebot.TeleBot.create_new_sticker_set:21 msgid "One or more emoji corresponding to the sticker" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:16 -#: telebot.TeleBot.create_new_sticker_set:21 +#: of telebot.TeleBot.add_sticker_to_set:21 +#: telebot.TeleBot.create_new_sticker_set:24 msgid "" "PNG image with the sticker, must be up to 512 kilobytes in size, " "dimensions must not exceed 512px, and either width or height must be " @@ -469,35 +493,42 @@ msgid "" "/form-data." msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:21 -#: telebot.TeleBot.create_new_sticker_set:26 +#: of telebot.TeleBot.add_sticker_to_set:26 +#: telebot.TeleBot.create_new_sticker_set:29 msgid "TGS animation with the sticker, uploaded using multipart/form-data." msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:24 -#: telebot.TeleBot.create_new_sticker_set:29 +#: of telebot.TeleBot.add_sticker_to_set:29 +#: telebot.TeleBot.create_new_sticker_set:32 msgid "WebM animation with the sticker, uploaded using multipart/form-data." msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:27 -#: telebot.TeleBot.create_new_sticker_set:40 +#: of telebot.TeleBot.add_sticker_to_set:32 +#: telebot.TeleBot.create_new_sticker_set:42 msgid "" "A JSON-serialized object for position where the mask should be placed on " "faces" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:30 +#: of telebot.TeleBot.add_sticker_to_set:35 +msgid "" +"A JSON-serialized list of 1-50 initial stickers to be added to the " +"sticker set" +msgstr "" + +#: of telebot.TeleBot.add_sticker_to_set:38 #: telebot.TeleBot.answer_callback_query:22 -#: telebot.TeleBot.answer_inline_query:35 +#: telebot.TeleBot.answer_inline_query:38 #: telebot.TeleBot.answer_pre_checkout_query:21 #: telebot.TeleBot.answer_shipping_query:18 #: telebot.TeleBot.close_forum_topic:13 -#: telebot.TeleBot.create_new_sticker_set:43 +#: telebot.TeleBot.create_new_sticker_set:56 #: telebot.TeleBot.delete_forum_topic:13 #: telebot.TeleBot.delete_sticker_from_set:6 #: telebot.TeleBot.edit_forum_topic:22 telebot.TeleBot.reopen_forum_topic:13 +#: telebot.TeleBot.set_sticker_keywords:11 #: telebot.TeleBot.set_sticker_position_in_set:11 -#: telebot.TeleBot.set_sticker_set_thumb:15 +#: telebot.TeleBot.set_sticker_set_thumbnail:15 #: telebot.TeleBot.unpin_all_forum_topic_messages:13 msgid "On success, True is returned." msgstr "" @@ -514,9 +545,10 @@ msgstr "" #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands -#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_webhook -#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link -#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_message_caption +#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_sticker_set +#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file +#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic +#: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text telebot.TeleBot.export_chat_invite_link @@ -542,15 +574,18 @@ msgstr "" #: telebot.TeleBot.send_message telebot.TeleBot.send_photo #: telebot.TeleBot.send_poll telebot.TeleBot.send_sticker #: telebot.TeleBot.send_venue telebot.TeleBot.send_video -#: telebot.TeleBot.send_video_note #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights +#: telebot.TeleBot.set_sticker_emoji_list telebot.TeleBot.set_sticker_keywords +#: telebot.TeleBot.set_sticker_mask_position #: telebot.TeleBot.set_sticker_position_in_set -#: telebot.TeleBot.set_sticker_set_thumb telebot.TeleBot.set_webhook +#: telebot.TeleBot.set_sticker_set_thumbnail +#: telebot.TeleBot.set_sticker_set_title telebot.TeleBot.set_webhook #: telebot.TeleBot.stop_message_live_location telebot.TeleBot.stop_poll #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat #: telebot.TeleBot.unpin_all_chat_messages @@ -560,34 +595,43 @@ msgstr "" msgid "Return type" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:31 +#: of telebot.TeleBot.add_sticker_to_set:39 #: telebot.TeleBot.answer_callback_query:23 -#: telebot.TeleBot.answer_inline_query:36 +#: telebot.TeleBot.answer_inline_query:39 #: telebot.TeleBot.answer_pre_checkout_query:22 #: telebot.TeleBot.answer_shipping_query:19 #: telebot.TeleBot.approve_chat_join_request:15 #: telebot.TeleBot.ban_chat_member:25 telebot.TeleBot.ban_chat_sender_chat:17 #: telebot.TeleBot.close:9 telebot.TeleBot.close_forum_topic:14 -#: telebot.TeleBot.create_new_sticker_set:44 +#: telebot.TeleBot.create_new_sticker_set:57 #: telebot.TeleBot.decline_chat_join_request:15 #: telebot.TeleBot.delete_chat_photo:13 #: telebot.TeleBot.delete_chat_sticker_set:11 #: telebot.TeleBot.delete_forum_topic:14 telebot.TeleBot.delete_message:23 #: telebot.TeleBot.delete_my_commands:17 -#: telebot.TeleBot.delete_sticker_from_set:7 telebot.TeleBot.delete_webhook:13 +#: telebot.TeleBot.delete_sticker_from_set:7 +#: telebot.TeleBot.delete_sticker_set:7 telebot.TeleBot.delete_webhook:13 #: telebot.TeleBot.edit_forum_topic:23 telebot.TeleBot.leave_chat:8 #: telebot.TeleBot.log_out:11 telebot.TeleBot.pin_chat_message:19 #: telebot.TeleBot.promote_chat_member:61 telebot.TeleBot.remove_webhook:4 #: telebot.TeleBot.reopen_forum_topic:14 -#: telebot.TeleBot.restrict_chat_member:48 telebot.TeleBot.send_chat_action:26 +#: telebot.TeleBot.restrict_chat_member:61 telebot.TeleBot.send_chat_action:26 +#: telebot.TeleBot.send_video_note:28 telebot.TeleBot.send_video_note:40 +#: telebot.TeleBot.send_video_note:43 #: telebot.TeleBot.set_chat_administrator_custom_title:18 #: telebot.TeleBot.set_chat_description:14 #: telebot.TeleBot.set_chat_menu_button:15 -#: telebot.TeleBot.set_chat_permissions:15 telebot.TeleBot.set_chat_photo:16 -#: telebot.TeleBot.set_chat_title:17 telebot.TeleBot.set_my_commands:18 +#: telebot.TeleBot.set_chat_permissions:21 telebot.TeleBot.set_chat_photo:16 +#: telebot.TeleBot.set_chat_title:17 +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:11 +#: telebot.TeleBot.set_my_commands:18 #: telebot.TeleBot.set_my_default_administrator_rights:18 +#: telebot.TeleBot.set_sticker_emoji_list:11 +#: telebot.TeleBot.set_sticker_keywords:12 +#: telebot.TeleBot.set_sticker_mask_position:12 #: telebot.TeleBot.set_sticker_position_in_set:12 -#: telebot.TeleBot.set_sticker_set_thumb:16 +#: telebot.TeleBot.set_sticker_set_thumbnail:16 +#: telebot.TeleBot.set_sticker_set_title:11 #: telebot.TeleBot.unban_chat_member:20 #: telebot.TeleBot.unban_chat_sender_chat:15 #: telebot.TeleBot.unpin_all_chat_messages:12 @@ -702,6 +746,12 @@ msgid "" "switch button" msgstr "" +#: of telebot.TeleBot.answer_inline_query:35 +msgid "" +"A JSON-serialized object describing a button to be shown above inline " +"query results" +msgstr "" + #: of telebot.TeleBot.answer_pre_checkout_query:1 msgid "" "Once the user has confirmed their payment and shipping details, the Bot " @@ -825,7 +875,7 @@ msgstr "" #: telebot.TeleBot.decline_chat_join_request:11 #: telebot.TeleBot.get_chat_member:8 telebot.TeleBot.get_user_profile_photos:6 #: telebot.TeleBot.promote_chat_member:11 -#: telebot.TeleBot.restrict_chat_member:11 +#: telebot.TeleBot.restrict_chat_member:14 #: telebot.TeleBot.set_chat_administrator_custom_title:10 #: telebot.TeleBot.unban_chat_member:13 msgid "Unique identifier of the target user" @@ -842,7 +892,9 @@ msgstr "" #: telebot.TeleBot.set_chat_menu_button:14 telebot.TeleBot.set_chat_photo:15 #: telebot.TeleBot.set_chat_title:16 telebot.TeleBot.set_my_commands:17 #: telebot.TeleBot.set_my_default_administrator_rights:17 -#: telebot.TeleBot.set_webhook:46 telebot.TeleBot.unban_chat_sender_chat:14 +#: telebot.TeleBot.set_my_description:14 telebot.TeleBot.set_my_name:12 +#: telebot.TeleBot.set_my_short_description:14 telebot.TeleBot.set_webhook:46 +#: telebot.TeleBot.unban_chat_sender_chat:14 #: telebot.TeleBot.unpin_all_chat_messages:11 #: telebot.TeleBot.unpin_chat_message:14 msgid "True on success." @@ -860,7 +912,7 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#banchatmember" msgstr "" -#: of telebot.TeleBot.ban_chat_member:8 telebot.TeleBot.restrict_chat_member:7 +#: of telebot.TeleBot.ban_chat_member:8 telebot.TeleBot.restrict_chat_member:10 msgid "" "Unique identifier for the target group or username of the target " "supergroup or channel (in the format @channelusername)" @@ -883,7 +935,12 @@ msgstr "" #: of telebot.TeleBot.ban_chat_member:24 #: telebot.TeleBot.delete_chat_sticker_set:10 telebot.TeleBot.delete_message:22 -#: telebot.TeleBot.delete_webhook:12 telebot.TeleBot.send_chat_action:25 +#: telebot.TeleBot.delete_sticker_set:6 telebot.TeleBot.delete_webhook:12 +#: telebot.TeleBot.send_chat_action:25 +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:10 +#: telebot.TeleBot.set_sticker_emoji_list:10 +#: telebot.TeleBot.set_sticker_mask_position:11 +#: telebot.TeleBot.set_sticker_set_title:10 msgid "Returns True on success." msgstr "" @@ -1241,26 +1298,24 @@ msgid "Identifier of a message thread, in which the message will be sent" msgstr "" #: of telebot.TeleBot.copy_message:45 telebot.TeleBot.forward_message:26 -#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:63 -#: telebot.TeleBot.send_audio:63 telebot.TeleBot.send_contact:44 -#: telebot.TeleBot.send_dice:35 telebot.TeleBot.send_document:56 +#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:66 +#: telebot.TeleBot.send_audio:66 telebot.TeleBot.send_contact:44 +#: telebot.TeleBot.send_dice:35 telebot.TeleBot.send_document:59 #: telebot.TeleBot.send_game:32 telebot.TeleBot.send_invoice:101 #: telebot.TeleBot.send_location:49 telebot.TeleBot.send_message:46 #: telebot.TeleBot.send_photo:48 telebot.TeleBot.send_poll:70 -#: telebot.TeleBot.send_sticker:39 telebot.TeleBot.send_venue:57 -#: telebot.TeleBot.send_video:64 telebot.TeleBot.send_video_note:48 -#: telebot.TeleBot.send_voice:49 +#: telebot.TeleBot.send_sticker:42 telebot.TeleBot.send_venue:57 +#: telebot.TeleBot.send_video:67 telebot.TeleBot.send_voice:49 msgid "On success, the sent Message is returned." msgstr "" #: of telebot.TeleBot.copy_message:46 telebot.TeleBot.forward_message:27 -#: telebot.TeleBot.reply_to:12 telebot.TeleBot.send_animation:64 -#: telebot.TeleBot.send_audio:64 telebot.TeleBot.send_contact:45 -#: telebot.TeleBot.send_dice:36 telebot.TeleBot.send_document:57 +#: telebot.TeleBot.reply_to:12 telebot.TeleBot.send_animation:67 +#: telebot.TeleBot.send_audio:67 telebot.TeleBot.send_contact:45 +#: telebot.TeleBot.send_dice:36 telebot.TeleBot.send_document:60 #: telebot.TeleBot.send_location:50 telebot.TeleBot.send_message:47 -#: telebot.TeleBot.send_photo:49 telebot.TeleBot.send_sticker:40 -#: telebot.TeleBot.send_venue:58 telebot.TeleBot.send_video:65 -#: telebot.TeleBot.send_video_note:49 +#: telebot.TeleBot.send_photo:49 telebot.TeleBot.send_sticker:43 +#: telebot.TeleBot.send_venue:58 telebot.TeleBot.send_video:68 msgid ":class:`telebot.types.Message`" msgstr "" @@ -1493,7 +1548,13 @@ msgid "" "https://core.telegram.org/bots/api#createnewstickerset" msgstr "" -#: of telebot.TeleBot.create_new_sticker_set:10 +#: of telebot.TeleBot.create_new_sticker_set:8 +msgid "" +"Fields *_sticker are deprecated, pass a list of stickers to stickers " +"parameter instead." +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:13 msgid "" "Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., " "animals). Can contain only English letters, digits and underscores. Must " @@ -1502,21 +1563,38 @@ msgid "" "characters." msgstr "" -#: of telebot.TeleBot.create_new_sticker_set:15 +#: of telebot.TeleBot.create_new_sticker_set:18 msgid "Sticker set title, 1-64 characters" msgstr "" -#: of telebot.TeleBot.create_new_sticker_set:32 +#: of telebot.TeleBot.create_new_sticker_set:35 msgid "" "Pass True, if a set of mask stickers should be created. Deprecated since " "Bot API 6.2, use sticker_type instead." msgstr "" -#: of telebot.TeleBot.create_new_sticker_set:36 +#: of telebot.TeleBot.create_new_sticker_set:39 +msgid "" +"Type of stickers in the set, pass “regular”, “mask”, or “custom_emoji”. " +"By default, a regular sticker set is created." +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:45 msgid "" -"Optional, Type of stickers in the set, pass “regular” or “mask”. Custom " -"emoji sticker sets can't be created via the Bot API at the moment. By " -"default, a regular sticker set is created." +"Pass True if stickers in the sticker set must be repainted to the color " +"of text when used in messages, the accent color if used as emoji status, " +"white on chat photos, or another appropriate color based on context; for " +"custom emoji sticker sets only" +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:50 +msgid "List of stickers to be added to the set" +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:53 +msgid "" +"Format of stickers in the set, must be one of “static”, “animated”, " +"“video”" msgstr "" #: of telebot.TeleBot.decline_chat_join_request:1 @@ -1656,6 +1734,10 @@ msgstr "" msgid "File identifier of the sticker" msgstr "" +#: of telebot.TeleBot.delete_sticker_set:1 +msgid "Use this method to delete a sticker set. Returns True on success." +msgstr "" + #: of telebot.TeleBot.delete_webhook:1 msgid "" "Use this method to remove webhook integration if you decide to switch " @@ -2171,6 +2253,9 @@ msgid "Number of members in the chat." msgstr "" #: of telebot.TeleBot.get_chat_member_count:9 +#: telebot.TeleBot.send_video_note:14 telebot.TeleBot.send_video_note:17 +#: telebot.TeleBot.send_video_note:20 telebot.TeleBot.send_video_note:31 +#: telebot.TeleBot.send_video_note:46 msgid ":obj:`int`" msgstr "" @@ -2237,7 +2322,7 @@ msgstr "" msgid "File identifier" msgstr "" -#: of telebot.TeleBot.get_file:12 telebot.TeleBot.upload_sticker_file:14 +#: of telebot.TeleBot.get_file:12 telebot.TeleBot.upload_sticker_file:21 msgid ":class:`telebot.types.File`" msgstr "" @@ -2296,7 +2381,7 @@ msgid "" msgstr "" #: of telebot.TeleBot.get_game_high_scores:10 telebot.TeleBot.retrieve_data:3 -#: telebot.TeleBot.set_game_score:5 telebot.TeleBot.set_sticker_set_thumb:9 +#: telebot.TeleBot.set_game_score:5 telebot.TeleBot.set_sticker_set_thumbnail:9 msgid "User identifier" msgstr "" @@ -2360,6 +2445,61 @@ msgstr "" msgid ":class:`telebot.types.ChatAdministratorRights`" msgstr "" +#: of telebot.TeleBot.get_my_description:1 +msgid "" +"Use this method to get the current bot description for the given user " +"language. Returns BotDescription on success." +msgstr "" + +#: of telebot.TeleBot.get_my_description:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getmydescription" +msgstr "" + +#: of telebot.TeleBot.get_my_description:6 +#: telebot.TeleBot.get_my_short_description:6 +msgid "A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.TeleBot.get_my_description:9 +msgid ":class:`telebot.types.BotDescription`" +msgstr "" + +#: of telebot.TeleBot.get_my_name:1 +msgid "" +"Use this method to get the current bot name for the given user language. " +"Returns BotName on success." +msgstr "" + +#: of telebot.TeleBot.get_my_name:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#getmyname" +msgstr "" + +#: of telebot.TeleBot.get_my_name:6 +msgid "Optional. A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.TeleBot.get_my_name:9 +msgid ":class:`telebot.types.BotName`" +msgstr "" + +#: of telebot.TeleBot.get_my_short_description:1 +msgid "" +"Use this method to get the current bot short description for the given " +"user language. Returns BotShortDescription on success." +msgstr "" + +#: of telebot.TeleBot.get_my_short_description:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getmyshortdescription" +msgstr "" + +#: of telebot.TeleBot.get_my_short_description:9 +msgid ":class:`telebot.types.BotShortDescription`" +msgstr "" + #: of telebot.TeleBot.get_state:1 msgid "" "Gets current state of a user. Not recommended to use this method. But it " @@ -3201,61 +3341,84 @@ msgid "" "https://core.telegram.org/bots/api#restrictchatmember" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:14 +#: of telebot.TeleBot.restrict_chat_member:8 +msgid "" +"Individual parameters are deprecated and will be removed, use " +"'permissions' instead." +msgstr "" + +#: of telebot.TeleBot.restrict_chat_member:17 msgid "" "Date when restrictions will be lifted for the user, unix time. If user is" " restricted for more than 366 days or less than 30 seconds from the " "current time, they are considered to be restricted forever" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:19 +#: of telebot.TeleBot.restrict_chat_member:22 msgid "" "Pass True, if the user can send text messages, contacts, locations and " "venues" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:22 +#: of telebot.TeleBot.restrict_chat_member:25 msgid "" "Pass True, if the user can send audios, documents, photos, videos, video " "notes and voice notes, implies can_send_messages" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:26 +#: of telebot.TeleBot.restrict_chat_member:29 msgid "Pass True, if the user is allowed to send polls, implies can_send_messages" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:29 +#: of telebot.TeleBot.restrict_chat_member:32 msgid "" "Pass True, if the user can send animations, games, stickers and use " "inline bots, implies can_send_media_messages" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:32 +#: of telebot.TeleBot.restrict_chat_member:35 msgid "" "Pass True, if the user may add web page previews to their messages, " "implies can_send_media_messages" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:36 +#: of telebot.TeleBot.restrict_chat_member:39 msgid "" "Pass True, if the user is allowed to change the chat title, photo and " "other settings. Ignored in public supergroups" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:40 +#: of telebot.TeleBot.restrict_chat_member:43 msgid "" "Pass True, if the user is allowed to invite new users to the chat, " "implies can_invite_users" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:44 +#: of telebot.TeleBot.restrict_chat_member:47 msgid "" "Pass True, if the user is allowed to pin messages. Ignored in public " "supergroups" msgstr "" -#: of telebot.TeleBot.restrict_chat_member:47 -#: telebot.TeleBot.set_chat_permissions:14 telebot.TeleBot.unban_chat_member:19 +#: of telebot.TeleBot.restrict_chat_member:50 +#: telebot.TeleBot.set_chat_permissions:14 +msgid "" +"Pass True if chat permissions are set independently. Otherwise, the " +"can_send_other_messages and can_add_web_page_previews permissions will " +"imply the can_send_messages, can_send_audios, can_send_documents, " +"can_send_photos, can_send_videos, can_send_video_notes, and " +"can_send_voice_notes permissions; the can_send_polls permission will " +"imply the can_send_messages permission." +msgstr "" + +#: of telebot.TeleBot.restrict_chat_member:56 +msgid "" +"Pass ChatPermissions object to set all permissions at once. Use this " +"param instead of passing all boolean parameters." +msgstr "" + +#: of telebot.TeleBot.restrict_chat_member:60 +#: telebot.TeleBot.set_chat_permissions:20 telebot.TeleBot.unban_chat_member:19 msgid "True on success" msgstr "" @@ -3429,6 +3592,12 @@ msgstr "" msgid "Pass True, if the animation should be sent as a spoiler" msgstr "" +#: of telebot.TeleBot.send_animation:63 telebot.TeleBot.send_audio:63 +#: telebot.TeleBot.send_document:56 telebot.TeleBot.send_video:64 +#: telebot.TeleBot.send_video_note:48 +msgid "Deprecated. Use thumbnail instead" +msgstr "" + #: of telebot.TeleBot.send_audio:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -3973,6 +4142,10 @@ msgstr "" msgid "to disable the notification" msgstr "" +#: of telebot.TeleBot.send_sticker:39 +msgid "Emoji associated with the sticker; only for just uploaded stickers" +msgstr "" + #: of telebot.TeleBot.send_venue:1 msgid "" "Use this method to send information about a venue. On success, the sent " @@ -4076,6 +4249,22 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideonote" msgstr "" +#: of telebot.TeleBot.send_video_note +msgid "param chat_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type chat_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note:7 +msgid ":obj:`int` or :obj:`str`" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param data" +msgstr "" + #: of telebot.TeleBot.send_video_note:9 msgid "" "Video note to send. Pass a file_id as String to send a video note that " @@ -4084,14 +4273,114 @@ msgid "" "unsupported" msgstr "" +#: of telebot.TeleBot.send_video_note +msgid "type data" +msgstr "" + +#: of telebot.TeleBot.send_video_note:11 telebot.TeleBot.send_video_note:37 +msgid ":obj:`str` or :class:`telebot.types.InputFile`" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param duration" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type duration" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param length" +msgstr "" + #: of telebot.TeleBot.send_video_note:16 msgid "Video width and height, i.e. diameter of the video message" msgstr "" +#: of telebot.TeleBot.send_video_note +msgid "type length" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param reply_to_message_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type reply_to_message_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param reply_markup" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type reply_markup" +msgstr "" + +#: of telebot.TeleBot.send_video_note:24 +msgid "" +":class:`telebot.types.InlineKeyboardMarkup` or " +":class:`telebot.types.ReplyKeyboardMarkup` or " +":class:`telebot.types.ReplyKeyboardRemove` or " +":class:`telebot.types.ForceReply`" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param disable_notification" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type disable_notification" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param timeout" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type timeout" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param thumbnail" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type thumbnail" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param allow_sending_without_reply" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type allow_sending_without_reply" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param protect_content" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type protect_content" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param message_thread_id" +msgstr "" + #: of telebot.TeleBot.send_video_note:45 msgid "Identifier of a message thread, in which the video note will be sent" msgstr "" +#: of telebot.TeleBot.send_video_note +msgid "type message_thread_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param thumb" +msgstr "" + #: of telebot.TeleBot.send_voice:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -4262,6 +4551,18 @@ msgstr "" msgid "New chat title, 1-255 characters" msgstr "" +#: of telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:1 +msgid "" +"Use this method to set the thumbnail of a custom emoji sticker set. " +"Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:7 +msgid "" +"Custom emoji identifier of a sticker from the sticker set; pass an empty " +"string to drop the thumbnail and use the first sticker as the thumbnail." +msgstr "" + #: of telebot.TeleBot.set_game_score:1 msgid "Sets the value of points in the game to a specific user." msgstr "" @@ -4331,6 +4632,77 @@ msgid "" "groups and supergroups will be changed." msgstr "" +#: of telebot.TeleBot.set_my_description:1 +msgid "" +"Use this method to change the bot's description, which is shown in the " +"chat with the bot if the chat is empty. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_my_description:5 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmydescription" +msgstr "" + +#: of telebot.TeleBot.set_my_description:7 +msgid "" +"New bot description; 0-512 characters. Pass an empty string to remove the" +" dedicated description for the given language." +msgstr "" + +#: of telebot.TeleBot.set_my_description:10 +msgid "" +"A two-letter ISO 639-1 language code. If empty, the description will be " +"applied to all users for whose language there is no dedicated " +"description." +msgstr "" + +#: of telebot.TeleBot.set_my_name:1 +msgid "Use this method to change the bot's name. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_my_name:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#setmyname" +msgstr "" + +#: of telebot.TeleBot.set_my_name:5 +msgid "" +"Optional. New bot name; 0-64 characters. Pass an empty string to remove " +"the dedicated name for the given language." +msgstr "" + +#: of telebot.TeleBot.set_my_name:8 +msgid "" +"Optional. A two-letter ISO 639-1 language code. If empty, the name will " +"be shown to all users for whose language there is no dedicated name." +msgstr "" + +#: of telebot.TeleBot.set_my_short_description:1 +msgid "" +"Use this method to change the bot's short description, which is shown on " +"the bot's profile page and is sent together with the link when users " +"share the bot. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_my_short_description:5 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmyshortdescription" +msgstr "" + +#: of telebot.TeleBot.set_my_short_description:7 +msgid "" +"New short description for the bot; 0-120 characters. Pass an empty string" +" to remove the dedicated short description for the given language." +msgstr "" + +#: of telebot.TeleBot.set_my_short_description:10 +msgid "" +"A two-letter ISO 639-1 language code. If empty, the short description " +"will be applied to all users for whose language there is no dedicated " +"short description." +msgstr "" + #: of telebot.TeleBot.set_state:1 msgid "Sets a new state of a user." msgstr "" @@ -4347,6 +4719,51 @@ msgstr "" msgid "new state. can be string, integer, or :class:`telebot.types.State`" msgstr "" +#: of telebot.TeleBot.set_sticker_emoji_list:1 +msgid "" +"Use this method to set the emoji list of a custom emoji sticker set. " +"Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_sticker_emoji_list:4 +msgid "Sticker identifier" +msgstr "" + +#: of telebot.TeleBot.set_sticker_emoji_list:7 +msgid "List of emoji" +msgstr "" + +#: of telebot.TeleBot.set_sticker_keywords:1 +msgid "" +"Use this method to change search keywords assigned to a regular or custom" +" emoji sticker. The sticker must belong to a sticker set created by the " +"bot. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_sticker_keywords:5 +#: telebot.TeleBot.set_sticker_mask_position:5 +msgid "File identifier of the sticker." +msgstr "" + +#: of telebot.TeleBot.set_sticker_keywords:8 +msgid "" +"A JSON-serialized list of 0-20 search keywords for the sticker with total" +" length of up to 64 characters" +msgstr "" + +#: of telebot.TeleBot.set_sticker_mask_position:1 +msgid "" +"Use this method to change the mask position of a mask sticker. The " +"sticker must belong to a sticker set that was created by the bot. Returns" +" True on success." +msgstr "" + +#: of telebot.TeleBot.set_sticker_mask_position:8 +msgid "" +"A JSON-serialized object for position where the mask should be placed on " +"faces." +msgstr "" + #: of telebot.TeleBot.set_sticker_position_in_set:1 msgid "" "Use this method to move a sticker in a set created by the bot to a " @@ -4363,19 +4780,47 @@ msgstr "" msgid "New sticker position in the set, zero-based" msgstr "" -#: of telebot.TeleBot.set_sticker_set_thumb:1 +#: of telebot.TeleBot.set_sticker_set_thumbnail:1 msgid "" "Use this method to set the thumbnail of a sticker set. Animated " "thumbnails can be set for animated sticker sets only. Returns True on " "success." msgstr "" -#: of telebot.TeleBot.set_sticker_set_thumb:4 +#: of telebot.TeleBot.set_sticker_set_thumbnail:4 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#setstickersetthumb" msgstr "" +#: of telebot.TeleBot.set_sticker_set_thumbnail:12 +msgid "" +"A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in " +"size and have a width and height of exactly 100px, or a .TGS animation " +"with a thumbnail up to 32 kilobytes in size (see " +"https://core.telegram.org/stickers#animated-sticker-requirements for " +"animated sticker technical requirements), or a WEBM video with the " +"thumbnail up to 32 kilobytes in size; see " +"https://core.telegram.org/stickers#video-sticker-requirements for video " +"sticker technical requirements. Pass a file_id as a String to send a file" +" that already exists on the Telegram servers, pass an HTTP URL as a " +"String for Telegram to get a file from the Internet, or upload a new one " +"using multipart/form-data. More information on Sending Files ». Animated " +"and video sticker set thumbnails can't be uploaded via HTTP URL. If " +"omitted, then the thumbnail is dropped and the first sticker is used as " +"the thumbnail." +msgstr "" + +#: of telebot.TeleBot.set_sticker_set_title:1 +msgid "" +"Use this method to set the title of a created sticker set. Returns True " +"on success." +msgstr "" + +#: of telebot.TeleBot.set_sticker_set_title:7 +msgid "New sticker set title" +msgstr "" + #: of telebot.TeleBot.set_update_listener:1 msgid "Sets a listener function to be called when a new update is received." msgstr "" @@ -4672,12 +5117,23 @@ msgstr "" #: of telebot.TeleBot.upload_sticker_file:9 msgid "" -"PNG image with the sticker, must be up to 512 kilobytes in size, " -"dimensions must not exceed 512px, and either width or height must be " -"exactly 512px." +"DEPRECATED: PNG image with the sticker, must be up to 512 kilobytes in " +"size, dimensions must not exceed 512px, and either width or height must " +"be exactly 512px." msgstr "" #: of telebot.TeleBot.upload_sticker_file:13 +msgid "" +"A file with the sticker in .WEBP, .PNG, .TGS, or .WEBM format. See " +"https://core.telegram.org/stickers for technical requirements. More " +"information on Sending Files »" +msgstr "" + +#: of telebot.TeleBot.upload_sticker_file:17 +msgid "One of \"static\", \"animated\", \"video\"." +msgstr "" + +#: of telebot.TeleBot.upload_sticker_file:20 msgid "On success, the sent file is returned." msgstr "" @@ -4923,3 +5379,28 @@ msgstr "" #~ msgid "The chat for which we want to handle new message." #~ msgstr "" +#~ msgid "" +#~ "Use this method to add a new " +#~ "sticker to a set created by the" +#~ " bot. It's required to pass " +#~ "`png_sticker` or `tgs_sticker`. Returns True" +#~ " on success." +#~ msgstr "" + +#~ msgid "" +#~ "Optional, Type of stickers in the " +#~ "set, pass “regular” or “mask”. Custom" +#~ " emoji sticker sets can't be created" +#~ " via the Bot API at the moment." +#~ " By default, a regular sticker set" +#~ " is created." +#~ msgstr "" + +#~ msgid "" +#~ "PNG image with the sticker, must " +#~ "be up to 512 kilobytes in size," +#~ " dimensions must not exceed 512px, " +#~ "and either width or height must be" +#~ " exactly 512px." +#~ msgstr "" + diff --git a/docs/source/locales/en/LC_MESSAGES/types.po b/docs/source/locales/en/LC_MESSAGES/types.po index db003a268..c846273fe 100644 --- a/docs/source/locales/en/LC_MESSAGES/types.po +++ b/docs/source/locales/en/LC_MESSAGES/types.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-02 19:24+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -23,9 +23,11 @@ msgid "Types of API" msgstr "" #: of telebot.types.Animation:1 telebot.types.Audio:1 -#: telebot.types.CallbackQuery:1 telebot.types.Chat:1 -#: telebot.types.ChatJoinRequest:1 telebot.types.ChatMember:1 -#: telebot.types.ChatMemberUpdated:1 telebot.types.ChatPhoto:1 +#: telebot.types.BotDescription:1 telebot.types.BotName:1 +#: telebot.types.BotShortDescription:1 telebot.types.CallbackQuery:1 +#: telebot.types.Chat:1 telebot.types.ChatJoinRequest:1 +#: telebot.types.ChatMember:1 telebot.types.ChatMemberUpdated:1 +#: telebot.types.ChatPhoto:1 telebot.types.ChatShared:1 #: telebot.types.ChosenInlineResult:1 telebot.types.Contact:1 #: telebot.types.Document:1 telebot.types.File:1 telebot.types.ForumTopic:1 #: telebot.types.ForumTopicClosed:1 telebot.types.ForumTopicCreated:1 @@ -41,8 +43,8 @@ msgstr "" #: telebot.types.ShippingQuery:1 telebot.types.Sticker:1 #: telebot.types.StickerSet:1 telebot.types.SuccessfulPayment:1 #: telebot.types.Update:1 telebot.types.UserProfilePhotos:1 -#: telebot.types.Venue:1 telebot.types.Video:1 telebot.types.VideoChatEnded:1 -#: telebot.types.VideoChatParticipantsInvited:1 +#: telebot.types.UserShared:1 telebot.types.Venue:1 telebot.types.Video:1 +#: telebot.types.VideoChatEnded:1 telebot.types.VideoChatParticipantsInvited:1 #: telebot.types.VideoChatScheduled:1 telebot.types.VideoChatStarted:1 #: telebot.types.VideoNote:1 telebot.types.Voice:1 telebot.types.WebhookInfo:1 #: telebot.types.WriteAccessAllowed:1 @@ -66,14 +68,16 @@ msgstr "" #: telebot.types.BotCommandScopeChat #: telebot.types.BotCommandScopeChatAdministrators #: telebot.types.BotCommandScopeChatMember telebot.types.BotCommandScopeDefault -#: telebot.types.CallbackQuery telebot.types.Chat -#: telebot.types.ChatAdministratorRights telebot.types.ChatInviteLink -#: telebot.types.ChatJoinRequest telebot.types.ChatLocation -#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned -#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember -#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted -#: telebot.types.ChatMemberUpdated telebot.types.ChatPermissions -#: telebot.types.ChatPhoto telebot.types.ChosenInlineResult +#: telebot.types.BotDescription telebot.types.BotName +#: telebot.types.BotShortDescription telebot.types.CallbackQuery +#: telebot.types.Chat telebot.types.ChatAdministratorRights +#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest +#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator +#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft +#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner +#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated +#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.ChatShared telebot.types.ChosenInlineResult #: telebot.types.Contact telebot.types.Dice telebot.types.Document #: telebot.types.File telebot.types.ForceReply telebot.types.ForumTopic #: telebot.types.ForumTopicCreated telebot.types.ForumTopicEdited @@ -95,15 +99,17 @@ msgstr "" #: telebot.types.InlineQueryResultGif telebot.types.InlineQueryResultLocation #: telebot.types.InlineQueryResultMpeg4Gif telebot.types.InlineQueryResultPhoto #: telebot.types.InlineQueryResultVenue telebot.types.InlineQueryResultVideo -#: telebot.types.InlineQueryResultVoice +#: telebot.types.InlineQueryResultVoice telebot.types.InlineQueryResultsButton #: telebot.types.InputContactMessageContent telebot.types.InputFile #: telebot.types.InputInvoiceMessageContent #: telebot.types.InputLocationMessageContent telebot.types.InputMediaAnimation #: telebot.types.InputMediaAudio telebot.types.InputMediaDocument #: telebot.types.InputMediaPhoto telebot.types.InputMediaVideo -#: telebot.types.InputTextMessageContent telebot.types.InputVenueMessageContent -#: telebot.types.Invoice telebot.types.KeyboardButton -#: telebot.types.KeyboardButtonPollType telebot.types.LabeledPrice +#: telebot.types.InputSticker telebot.types.InputTextMessageContent +#: telebot.types.InputVenueMessageContent telebot.types.Invoice +#: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType +#: telebot.types.KeyboardButtonRequestChat +#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice #: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message @@ -117,11 +123,13 @@ msgstr "" #: telebot.types.ShippingAddress telebot.types.ShippingOption #: telebot.types.ShippingOption.add_price telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet -#: telebot.types.SuccessfulPayment telebot.types.Update telebot.types.User -#: telebot.types.UserProfilePhotos telebot.types.Venue telebot.types.Video +#: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat +#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos +#: telebot.types.UserShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo +#: telebot.types.WriteAccessAllowed msgid "Parameters" msgstr "" @@ -183,14 +191,16 @@ msgstr "" #: telebot.types.BotCommandScopeChat #: telebot.types.BotCommandScopeChatAdministrators #: telebot.types.BotCommandScopeChatMember telebot.types.BotCommandScopeDefault -#: telebot.types.CallbackQuery telebot.types.Chat -#: telebot.types.ChatAdministratorRights telebot.types.ChatInviteLink -#: telebot.types.ChatJoinRequest telebot.types.ChatLocation -#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned -#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember -#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted -#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference -#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.BotDescription telebot.types.BotName +#: telebot.types.BotShortDescription telebot.types.CallbackQuery +#: telebot.types.Chat telebot.types.ChatAdministratorRights +#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest +#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator +#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft +#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner +#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated +#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions +#: telebot.types.ChatPhoto telebot.types.ChatShared #: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice #: telebot.types.Document telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game @@ -211,15 +221,17 @@ msgstr "" #: telebot.types.InlineQueryResultGif telebot.types.InlineQueryResultLocation #: telebot.types.InlineQueryResultMpeg4Gif telebot.types.InlineQueryResultPhoto #: telebot.types.InlineQueryResultVenue telebot.types.InlineQueryResultVideo -#: telebot.types.InlineQueryResultVoice +#: telebot.types.InlineQueryResultVoice telebot.types.InlineQueryResultsButton #: telebot.types.InputContactMessageContent #: telebot.types.InputInvoiceMessageContent #: telebot.types.InputLocationMessageContent telebot.types.InputMediaAnimation #: telebot.types.InputMediaAudio telebot.types.InputMediaDocument #: telebot.types.InputMediaPhoto telebot.types.InputMediaVideo -#: telebot.types.InputTextMessageContent telebot.types.InputVenueMessageContent -#: telebot.types.Invoice telebot.types.KeyboardButton -#: telebot.types.KeyboardButtonPollType telebot.types.LabeledPrice +#: telebot.types.InputSticker telebot.types.InputTextMessageContent +#: telebot.types.InputVenueMessageContent telebot.types.Invoice +#: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType +#: telebot.types.KeyboardButtonRequestChat +#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice #: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message @@ -232,8 +244,9 @@ msgstr "" #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingOption.add_price #: telebot.types.ShippingQuery telebot.types.Sticker telebot.types.StickerSet -#: telebot.types.SuccessfulPayment telebot.types.Update telebot.types.User -#: telebot.types.UserProfilePhotos telebot.types.Venue telebot.types.Video +#: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat +#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos +#: telebot.types.UserShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -248,20 +261,22 @@ msgstr "" #: telebot.types.BotCommandScopeChat:12 #: telebot.types.BotCommandScopeChatAdministrators:12 #: telebot.types.BotCommandScopeChatMember:15 -#: telebot.types.BotCommandScopeDefault:8 telebot.types.CallbackQuery:30 -#: telebot.types.Chat:109 telebot.types.ChatAdministratorRights:46 -#: telebot.types.ChatInviteLink:34 telebot.types.ChatJoinRequest:20 -#: telebot.types.ChatLocation:11 telebot.types.ChatMemberAdministrator:59 -#: telebot.types.ChatMemberBanned:15 telebot.types.ChatMemberLeft:11 -#: telebot.types.ChatMemberMember:11 telebot.types.ChatMemberOwner:17 -#: telebot.types.ChatMemberRestricted:47 telebot.types.ChatMemberUpdated:24 -#: telebot.types.ChatPermissions:38 telebot.types.ChatPhoto:21 +#: telebot.types.BotCommandScopeDefault:8 telebot.types.BotDescription:8 +#: telebot.types.BotName:8 telebot.types.BotShortDescription:8 +#: telebot.types.CallbackQuery:30 telebot.types.Chat:109 +#: telebot.types.ChatAdministratorRights:46 telebot.types.ChatInviteLink:34 +#: telebot.types.ChatJoinRequest:27 telebot.types.ChatLocation:11 +#: telebot.types.ChatMemberAdministrator:59 telebot.types.ChatMemberBanned:15 +#: telebot.types.ChatMemberLeft:11 telebot.types.ChatMemberMember:11 +#: telebot.types.ChatMemberOwner:17 telebot.types.ChatMemberRestricted:61 +#: telebot.types.ChatMemberUpdated:27 telebot.types.ChatPermissions:56 +#: telebot.types.ChatPhoto:21 telebot.types.ChatShared:15 #: telebot.types.ChosenInlineResult:21 telebot.types.Contact:22 #: telebot.types.Dice:11 telebot.types.Document:26 telebot.types.File:21 #: telebot.types.ForceReply:18 telebot.types.ForumTopic:17 #: telebot.types.ForumTopicCreated:14 telebot.types.Game:25 -#: telebot.types.GameHighScore:14 telebot.types.InlineKeyboardButton:45 -#: telebot.types.InlineKeyboardMarkup:22 telebot.types.InlineQuery:26 +#: telebot.types.GameHighScore:14 telebot.types.InlineKeyboardButton:49 +#: telebot.types.InlineKeyboardMarkup:28 telebot.types.InlineQuery:26 #: telebot.types.InlineQueryResultArticle:38 #: telebot.types.InlineQueryResultAudio:40 #: telebot.types.InlineQueryResultCachedAudio:31 @@ -281,31 +296,35 @@ msgstr "" #: telebot.types.InlineQueryResultVenue:51 #: telebot.types.InlineQueryResultVideo:53 #: telebot.types.InlineQueryResultVoice:37 +#: telebot.types.InlineQueryResultsButton:22 #: telebot.types.InputContactMessageContent:17 #: telebot.types.InputInvoiceMessageContent:75 #: telebot.types.InputLocationMessageContent:26 #: telebot.types.InputMediaAnimation:40 telebot.types.InputMediaAudio:37 #: telebot.types.InputMediaDocument:32 telebot.types.InputMediaPhoto:24 -#: telebot.types.InputMediaVideo:43 telebot.types.InputTextMessageContent:19 +#: telebot.types.InputMediaVideo:43 telebot.types.InputSticker:18 +#: telebot.types.InputTextMessageContent:19 #: telebot.types.InputVenueMessageContent:30 telebot.types.Invoice:22 -#: telebot.types.KeyboardButton:25 telebot.types.KeyboardButtonPollType:9 -#: telebot.types.LabeledPrice:13 telebot.types.Location:25 -#: telebot.types.LoginUrl:24 telebot.types.MaskPosition:20 -#: telebot.types.MenuButtonCommands:8 telebot.types.MenuButtonDefault:8 -#: telebot.types.MenuButtonWebApp:15 telebot.types.Message:246 -#: telebot.types.MessageAutoDeleteTimerChanged:8 telebot.types.MessageEntity:32 -#: telebot.types.MessageID:8 telebot.types.OrderInfo:17 -#: telebot.types.PhotoSize:21 telebot.types.Poll:47 telebot.types.PollAnswer:15 -#: telebot.types.PollOption:11 telebot.types.PreCheckoutQuery:28 -#: telebot.types.ProximityAlertTriggered:14 +#: telebot.types.KeyboardButton:33 telebot.types.KeyboardButtonPollType:9 +#: telebot.types.KeyboardButtonRequestChat:35 +#: telebot.types.KeyboardButtonRequestUser:18 telebot.types.LabeledPrice:13 +#: telebot.types.Location:25 telebot.types.LoginUrl:24 +#: telebot.types.MaskPosition:20 telebot.types.MenuButtonCommands:8 +#: telebot.types.MenuButtonDefault:8 telebot.types.MenuButtonWebApp:15 +#: telebot.types.Message:252 telebot.types.MessageAutoDeleteTimerChanged:8 +#: telebot.types.MessageEntity:32 telebot.types.MessageID:8 +#: telebot.types.OrderInfo:17 telebot.types.PhotoSize:21 telebot.types.Poll:47 +#: telebot.types.PollAnswer:15 telebot.types.PollOption:11 +#: telebot.types.PreCheckoutQuery:28 telebot.types.ProximityAlertTriggered:14 #: telebot.types.ReplyKeyboardMarkup:49 telebot.types.ReplyKeyboardRemove:18 #: telebot.types.SentWebAppMessage:9 telebot.types.ShippingAddress:23 #: telebot.types.ShippingOption:14 telebot.types.ShippingQuery:17 -#: telebot.types.Sticker:49 telebot.types.StickerSet:30 -#: telebot.types.SuccessfulPayment:28 telebot.types.Update:61 +#: telebot.types.Sticker:54 telebot.types.StickerSet:30 +#: telebot.types.SuccessfulPayment:28 +#: telebot.types.SwitchInlineQueryChosenChat:22 telebot.types.Update:61 #: telebot.types.User:41 telebot.types.UserProfilePhotos:11 -#: telebot.types.Venue:27 telebot.types.Video:35 telebot.types.VideoChatEnded:8 -#: telebot.types.VideoChatParticipantsInvited:8 +#: telebot.types.UserShared:15 telebot.types.Venue:27 telebot.types.Video:35 +#: telebot.types.VideoChatEnded:8 telebot.types.VideoChatParticipantsInvited:8 #: telebot.types.VideoChatScheduled:9 telebot.types.VideoNote:24 #: telebot.types.Voice:23 telebot.types.WebAppData:12 #: telebot.types.WebAppInfo:8 telebot.types.WebhookInfo:37 @@ -320,14 +339,16 @@ msgstr "" #: telebot.types.BotCommandScopeChat #: telebot.types.BotCommandScopeChatAdministrators #: telebot.types.BotCommandScopeChatMember telebot.types.BotCommandScopeDefault -#: telebot.types.CallbackQuery telebot.types.Chat -#: telebot.types.ChatAdministratorRights telebot.types.ChatInviteLink -#: telebot.types.ChatJoinRequest telebot.types.ChatLocation -#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned -#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember -#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted -#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference -#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.BotDescription telebot.types.BotName +#: telebot.types.BotShortDescription telebot.types.CallbackQuery +#: telebot.types.Chat telebot.types.ChatAdministratorRights +#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest +#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator +#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft +#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner +#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated +#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions +#: telebot.types.ChatPhoto telebot.types.ChatShared #: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice #: telebot.types.Document telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game @@ -348,15 +369,17 @@ msgstr "" #: telebot.types.InlineQueryResultGif telebot.types.InlineQueryResultLocation #: telebot.types.InlineQueryResultMpeg4Gif telebot.types.InlineQueryResultPhoto #: telebot.types.InlineQueryResultVenue telebot.types.InlineQueryResultVideo -#: telebot.types.InlineQueryResultVoice +#: telebot.types.InlineQueryResultVoice telebot.types.InlineQueryResultsButton #: telebot.types.InputContactMessageContent #: telebot.types.InputInvoiceMessageContent #: telebot.types.InputLocationMessageContent telebot.types.InputMediaAnimation #: telebot.types.InputMediaAudio telebot.types.InputMediaDocument #: telebot.types.InputMediaPhoto telebot.types.InputMediaVideo -#: telebot.types.InputTextMessageContent telebot.types.InputVenueMessageContent -#: telebot.types.Invoice telebot.types.KeyboardButton -#: telebot.types.KeyboardButtonPollType telebot.types.LabeledPrice +#: telebot.types.InputSticker telebot.types.InputTextMessageContent +#: telebot.types.InputVenueMessageContent telebot.types.Invoice +#: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType +#: telebot.types.KeyboardButtonRequestChat +#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice #: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message @@ -369,8 +392,9 @@ msgstr "" #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet -#: telebot.types.SuccessfulPayment telebot.types.Update telebot.types.User -#: telebot.types.UserProfilePhotos telebot.types.Venue telebot.types.Video +#: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat +#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos +#: telebot.types.UserShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -703,6 +727,56 @@ msgstr "" msgid ":class:`telebot.types.BotCommandScopeDefault`" msgstr "" +#: of telebot.types.BotDescription:1 +msgid "This object represents a bot description." +msgstr "" + +#: of telebot.types.BotDescription:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#botdescription" +msgstr "" + +#: of telebot.types.BotDescription:5 +msgid "Bot description" +msgstr "" + +#: of telebot.types.BotDescription:9 +msgid ":class:`telebot.types.BotDescription`" +msgstr "" + +#: of telebot.types.BotName:1 +msgid "This object represents a bot name." +msgstr "" + +#: of telebot.types.BotName:3 +msgid "Telegram Documentation: https://core.telegram.org/bots/api#botname" +msgstr "" + +#: of telebot.types.BotName:5 +msgid "The bot name" +msgstr "" + +#: of telebot.types.BotName:9 +msgid ":class:`BotName`" +msgstr "" + +#: of telebot.types.BotShortDescription:1 +msgid "This object represents a bot short description." +msgstr "" + +#: of telebot.types.BotShortDescription:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#botshortdescription" +msgstr "" + +#: of telebot.types.BotShortDescription:5 +msgid "Bot short description" +msgstr "" + +#: of telebot.types.BotShortDescription:9 +msgid ":class:`telebot.types.BotShortDescription`" +msgstr "" + #: of telebot.types.CallbackQuery:1 msgid "" "This object represents an incoming callback query from a callback button " @@ -1120,20 +1194,31 @@ msgid "User that sent the join request" msgstr "" #: of telebot.types.ChatJoinRequest:11 +msgid "" +"Optional. Identifier of a private chat with the user who sent the join " +"request. This number may have more than 32 significant bits and some " +"programming languages may have difficulty/silent defects in interpreting " +"it. But it has at most 52 significant bits, so a 64-bit integer or " +"double-precision float type are safe for storing this identifier. The bot" +" can use this identifier for 24 hours to send messages until the join " +"request is processed, assuming no other administrator contacted the user." +msgstr "" + +#: of telebot.types.ChatJoinRequest:18 msgid "Date the request was sent in Unix time" msgstr "" -#: of telebot.types.ChatJoinRequest:14 +#: of telebot.types.ChatJoinRequest:21 msgid "Optional. Bio of the user." msgstr "" -#: of telebot.types.ChatJoinRequest:17 +#: of telebot.types.ChatJoinRequest:24 msgid "" "Optional. Chat invite link that was used by the user to send the join " "request" msgstr "" -#: of telebot.types.ChatJoinRequest:21 +#: of telebot.types.ChatJoinRequest:28 msgid ":class:`telebot.types.ChatJoinRequest`" msgstr "" @@ -1177,7 +1262,7 @@ msgstr "" msgid ":class:`telebot.types.ChatMemberMember`" msgstr "" -#: of telebot.types.ChatMember:7 telebot.types.ChatMemberRestricted:48 +#: of telebot.types.ChatMember:7 telebot.types.ChatMemberRestricted:62 msgid ":class:`telebot.types.ChatMemberRestricted`" msgstr "" @@ -1328,26 +1413,44 @@ msgid "" msgstr "" #: of telebot.types.ChatMemberRestricted:29 -msgid "" -"True, if the user is allowed to send audios, documents, photos, videos, " -"video notes and voice notes" +msgid "True, if the user is allowed to send audios" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:32 +msgid "True, if the user is allowed to send documents" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:35 +msgid "True, if the user is allowed to send photos" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:38 +msgid "True, if the user is allowed to send videos" msgstr "" -#: of telebot.types.ChatMemberRestricted:33 +#: of telebot.types.ChatMemberRestricted:41 +msgid "True, if the user is allowed to send video notes" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:44 +msgid "True, if the user is allowed to send voice notes" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:47 msgid "True, if the user is allowed to send polls" msgstr "" -#: of telebot.types.ChatMemberRestricted:36 +#: of telebot.types.ChatMemberRestricted:50 msgid "" "True, if the user is allowed to send animations, games, stickers and use " "inline bots" msgstr "" -#: of telebot.types.ChatMemberRestricted:40 +#: of telebot.types.ChatMemberRestricted:54 msgid "True, if the user is allowed to add web page previews to their messages" msgstr "" -#: of telebot.types.ChatMemberRestricted:43 +#: of telebot.types.ChatMemberRestricted:57 msgid "" "Date when restrictions will be lifted for this user; unix time. If 0, " "then the user is restricted forever" @@ -1389,7 +1492,11 @@ msgid "" "for joining by invite link events only." msgstr "" -#: of telebot.types.ChatMemberUpdated:25 +#: of telebot.types.ChatMemberUpdated:24 +msgid "Optional. True, if the user joined the chat via a chat folder invite link" +msgstr "" + +#: of telebot.types.ChatMemberUpdated:28 msgid ":class:`telebot.types.ChatMemberUpdated`" msgstr "" @@ -1421,52 +1528,76 @@ msgid "" msgstr "" #: of telebot.types.ChatPermissions:9 -msgid "" -"Optional. True, if the user is allowed to send audios, documents, photos," -" videos, video notes and voice notes, implies can_send_messages" +msgid "Optional. True, if the user is allowed to send audios" msgstr "" -#: of telebot.types.ChatPermissions:13 +#: of telebot.types.ChatPermissions:12 +msgid "Optional. True, if the user is allowed to send documents" +msgstr "" + +#: of telebot.types.ChatPermissions:15 +msgid "Optional. True, if the user is allowed to send photos" +msgstr "" + +#: of telebot.types.ChatPermissions:18 +msgid "Optional. True, if the user is allowed to send videos" +msgstr "" + +#: of telebot.types.ChatPermissions:21 +msgid "Optional. True, if the user is allowed to send video notes" +msgstr "" + +#: of telebot.types.ChatPermissions:24 +msgid "Optional. True, if the user is allowed to send voice notes" +msgstr "" + +#: of telebot.types.ChatPermissions:27 msgid "" "Optional. True, if the user is allowed to send polls, implies " "can_send_messages" msgstr "" -#: of telebot.types.ChatPermissions:16 +#: of telebot.types.ChatPermissions:30 msgid "" "Optional. True, if the user is allowed to send animations, games, " -"stickers and use inline bots, implies can_send_media_messages" +"stickers and use inline bots" msgstr "" -#: of telebot.types.ChatPermissions:20 +#: of telebot.types.ChatPermissions:34 msgid "" "Optional. True, if the user is allowed to add web page previews to their " -"messages, implies can_send_media_messages" +"messages" msgstr "" -#: of telebot.types.ChatPermissions:24 +#: of telebot.types.ChatPermissions:38 msgid "" "Optional. True, if the user is allowed to change the chat title, photo " "and other settings. Ignored in public supergroups" msgstr "" -#: of telebot.types.ChatPermissions:28 +#: of telebot.types.ChatPermissions:42 msgid "Optional. True, if the user is allowed to invite new users to the chat" msgstr "" -#: of telebot.types.ChatPermissions:31 +#: of telebot.types.ChatPermissions:45 msgid "" "Optional. True, if the user is allowed to pin messages. Ignored in public" " supergroups" msgstr "" -#: of telebot.types.ChatPermissions:34 +#: of telebot.types.ChatPermissions:48 msgid "" "Optional. True, if the user is allowed to create forum topics. If omitted" " defaults to the value of can_pin_messages" msgstr "" -#: of telebot.types.ChatPermissions:39 +#: of telebot.types.ChatPermissions:52 +msgid "" +"deprecated. True, if the user is allowed to send audios, documents, " +"photos, videos, video notes and voice notes" +msgstr "" + +#: of telebot.types.ChatPermissions:57 msgid ":class:`telebot.types.ChatPermissions`" msgstr "" @@ -1508,6 +1639,36 @@ msgstr "" msgid ":class:`telebot.types.ChatPhoto`" msgstr "" +#: of telebot.types.ChatShared:1 +msgid "" +"This object contains information about the chat whose identifier was " +"shared with the bot using a `telebot.types.KeyboardButtonRequestChat` " +"button." +msgstr "" + +#: of telebot.types.ChatShared:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#Chatshared" +msgstr "" + +#: of telebot.types.ChatShared:6 telebot.types.UserShared:6 +msgid "identifier of the request" +msgstr "" + +#: of telebot.types.ChatShared:9 +msgid "" +"Identifier of the shared chat. This number may have more than 32 " +"significant bits and some programming languages may have " +"difficulty/silent defects in interpreting it. But it has at most 52 " +"significant bits, so a 64-bit integer or double-precision float type are " +"safe for storing this identifier. The bot may not have access to the chat" +" and could be unable to use this identifier, unless the chat is already " +"known to the bot by some other means." +msgstr "" + +#: of telebot.types.ChatShared:16 +msgid ":class:`telebot.types.ChatShared`" +msgstr "" + #: of telebot.types.ChosenInlineResult:1 msgid "" "Represents a result of an inline query that was chosen by the user and " @@ -1915,12 +2076,14 @@ msgid "" msgstr "" #: of telebot.types.InlineKeyboardButton:3 +#: telebot.types.SwitchInlineQueryChosenChat:4 msgid "" "Telegram Documentation: " "https://core.telegram.org/bots/api#inlinekeyboardbutton" msgstr "" #: of telebot.types.InlineKeyboardButton:5 +#: telebot.types.InlineQueryResultsButton:6 msgid "Label text on the button" msgstr "" @@ -1974,19 +2137,26 @@ msgstr "" #: of telebot.types.InlineKeyboardButton:37 msgid "" +"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 query in the input field" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:41 +msgid "" "Optional. Description of the game that will be launched when the user " "presses the button. NOTE: This type of button must always be the first " "button in the first row." msgstr "" -#: of telebot.types.InlineKeyboardButton:41 +#: of telebot.types.InlineKeyboardButton:45 msgid "" "Optional. Specify True, to send a Pay button. NOTE: This type of button " "must always be the first button in the first row and can only be used in " "invoice messages." msgstr "" -#: of telebot.types.InlineKeyboardButton:46 +#: of telebot.types.InlineKeyboardButton:50 msgid ":class:`telebot.types.InlineKeyboardButton`" msgstr "" @@ -2004,19 +2174,23 @@ msgstr "" msgid "Example of a custom keyboard with buttons." msgstr "" -#: of telebot.types.InlineKeyboardMarkup:16 +#: of telebot.types.InlineKeyboardMarkup:19 msgid "" "Telegram Documentation: " "https://core.telegram.org/bots/api#inlinekeyboardmarkup" msgstr "" -#: of telebot.types.InlineKeyboardMarkup:18 +#: of telebot.types.InlineKeyboardMarkup:21 msgid "" ":obj:`list` of button rows, each represented by an :obj:`list` of " ":class:`telebot.types.InlineKeyboardButton` objects" msgstr "" -#: of telebot.types.InlineKeyboardMarkup:23 +#: of telebot.types.InlineKeyboardMarkup:25 +msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row" +msgstr "" + +#: of telebot.types.InlineKeyboardMarkup:29 #: telebot.types.InlineKeyboardMarkup.add:17 #: telebot.types.InlineKeyboardMarkup.row:12 msgid ":class:`telebot.types.InlineKeyboardMarkup`" @@ -3165,12 +3339,58 @@ msgstr "" msgid ":class:`telebot.types.InlineQueryResultVoice`" msgstr "" +#: of telebot.types.InlineQueryResultsButton:1 telebot.types.LabeledPrice:1 +msgid "" +"Bases: :py:class:`telebot.types.JsonSerializable`, " +":py:class:`telebot.types.Dictionaryable`" +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:1 +msgid "" +"This object represents a button to be shown above inline query results. " +"You must use exactly one of the optional fields." +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#inlinequeryresultsbutton" +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:9 +msgid "" +"Optional. Description of the Web App that will be launched when the user " +"presses the button. The Web App will be able to switch back to the inline" +" mode using the method web_app_switch_inline_query inside the Web App." +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:13 +msgid "" +"Optional. Deep-linking parameter for the /start message sent to the bot " +"when a user presses the button. 1-64 characters, only A-Z, a-z, 0-9, _ " +"and - are allowed. Example: An inline bot that sends YouTube videos can " +"ask the user to connect the bot to their YouTube account to adapt search " +"results accordingly. To do this, it displays a 'Connect your YouTube " +"account' button above the results, or even before showing any. The user " +"presses the button, switches to a private chat with the bot and, in doing" +" so, passes a start parameter that instructs the bot to return an OAuth " +"link. Once done, the bot can offer a switch_inline button so that the " +"user can easily return to the chat where they wanted to use the bot's " +"inline capabilities." +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:23 +msgid ":class:`InlineQueryResultsButton`" +msgstr "" + #: of telebot.types.InputContactMessageContent:1 #: telebot.types.InputInvoiceMessageContent:1 #: telebot.types.InputLocationMessageContent:1 #: telebot.types.InputTextMessageContent:1 #: telebot.types.InputVenueMessageContent:1 #: telebot.types.KeyboardButtonPollType:1 +#: telebot.types.KeyboardButtonRequestChat:1 +#: telebot.types.KeyboardButtonRequestUser:1 msgid "Bases: :py:class:`telebot.types.Dictionaryable`" msgstr "" @@ -3367,7 +3587,8 @@ msgstr "" msgid ":class:`telebot.types.InputLocationMessageContent`" msgstr "" -#: of telebot.types.InputMedia:1 telebot.types.KeyboardButton:1 +#: of telebot.types.InputMedia:1 telebot.types.InputSticker:1 +#: telebot.types.KeyboardButton:1 msgid "" "Bases: :py:class:`telebot.types.Dictionaryable`, " ":py:class:`telebot.types.JsonSerializable`" @@ -3560,6 +3781,39 @@ msgstr "" msgid ":class:`telebot.types.InputMediaVideo`" msgstr "" +#: of telebot.types.InputSticker:1 +msgid "This object describes a sticker to be added to a sticker set." +msgstr "" + +#: of telebot.types.InputSticker:3 +msgid "" +"The added sticker. Pass a file_id as a String to send a file that already" +" exists on the Telegram servers, pass an HTTP URL as a String for " +"Telegram to get a file from the Internet, or upload a new one using " +"multipart/form-data. Animated and video stickers can't be uploaded via " +"HTTP URL." +msgstr "" + +#: of telebot.types.InputSticker:8 +msgid "One or more(up to 20) emoji(s) corresponding to the sticker" +msgstr "" + +#: of telebot.types.InputSticker:11 +msgid "" +"Optional. Position where the mask should be placed on faces. For “mask” " +"stickers only." +msgstr "" + +#: of telebot.types.InputSticker:14 +msgid "" +"Optional. List of 0-20 search keywords for the sticker with total length " +"of up to 64 characters. For “regular” and “custom_emoji” stickers only." +msgstr "" + +#: of telebot.types.InputSticker:19 +msgid ":class:`telebot.types.InputSticker`" +msgstr "" + #: of telebot.types.InputTextMessageContent:1 msgid "" "Represents the content of a text message to be sent as the result of an " @@ -3726,7 +3980,21 @@ msgid "" "service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:26 +#: of telebot.types.KeyboardButton:25 +msgid "" +"Optional. If specified, pressing the button will open a list of suitable " +"users. Tapping on any user will send their identifier to the bot in a " +"“user_shared” service message. Available in private chats only." +msgstr "" + +#: of telebot.types.KeyboardButton:29 +msgid "" +"Optional. If specified, pressing the button will open a list of suitable " +"chats. Tapping on a chat will send its identifier to the bot in a " +"“chat_shared” service message. Available in private chats only." +msgstr "" + +#: of telebot.types.KeyboardButton:34 msgid ":class:`telebot.types.KeyboardButton`" msgstr "" @@ -3754,10 +4022,111 @@ msgstr "" msgid ":class:`telebot.types.KeyboardButtonPollType`" msgstr "" -#: of telebot.types.LabeledPrice:1 +#: of telebot.types.KeyboardButtonRequestChat:1 msgid "" -"Bases: :py:class:`telebot.types.JsonSerializable`, " -":py:class:`telebot.types.Dictionaryable`" +"This object defines the criteria used to request a suitable chat. The " +"identifier of the selected chat will be shared with the bot when the " +"corresponding button is pressed." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#keyboardbuttonrequestchat" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:6 +msgid "" +"Signed 32-bit identifier of the request, which will be received back in " +"the ChatShared object. Must be unique within the message" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:10 +msgid "" +"Pass True to request a channel chat, pass False to request a group or a " +"supergroup chat." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:13 +msgid "" +"Optional. Pass True to request a forum supergroup, pass False to request " +"a non-forum chat. If not specified, no additional restrictions are " +"applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:17 +msgid "" +"Optional. Pass True to request a supergroup or a channel with a username," +" pass False to request a chat without a username. If not specified, no " +"additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:21 +msgid "" +"Optional. Pass True to request a chat owned by the user. Otherwise, no " +"additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:24 +msgid "" +"Optional. A JSON-serialized object listing the required administrator " +"rights of the user in the chat. The rights must be a superset of " +"bot_administrator_rights. If not specified, no additional restrictions " +"are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:28 +msgid "" +"Optional. A JSON-serialized object listing the required administrator " +"rights of the bot in the chat. The rights must be a subset of " +"user_administrator_rights. If not specified, no additional restrictions " +"are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:32 +msgid "" +"Optional. Pass True to request a chat where the bot is a member. " +"Otherwise, no additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:36 +msgid ":class:`telebot.types.KeyboardButtonRequestChat`" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:1 +msgid "" +"This object defines the criteria used to request a suitable user. The " +"identifier of the selected user will be shared with the bot when the " +"corresponding button is pressed." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#keyboardbuttonrequestuser" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:6 +msgid "" +"Signed 32-bit identifier of the request, which will be received back in " +"the UserShared object. Must be unique within the message" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:10 +msgid "" +"Optional. Pass True to request a bot, pass False to request a regular " +"user. If not specified, no additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:14 +msgid "" +"Optional. Pass True to request a premium user, pass False to request a " +"non-premium user. If not specified, no additional restrictions are " +"applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:19 +msgid ":class:`telebot.types.KeyboardButtonRequestUser`" msgstr "" #: of telebot.types.LabeledPrice:1 @@ -4306,78 +4675,86 @@ msgid "" msgstr "" #: of telebot.types.Message:194 +msgid "Optional. Service message: a user was shared with the bot" +msgstr "" + +#: of telebot.types.Message:197 +msgid "Optional. Service message: a chat was shared with the bot" +msgstr "" + +#: of telebot.types.Message:200 msgid "" "Optional. The domain name of the website on which the user has logged in." " More about Telegram Login »" msgstr "" -#: of telebot.types.Message:198 +#: of telebot.types.Message:204 msgid "" "Optional. Service message: the user allowed the bot added to the " "attachment menu to write messages" msgstr "" -#: of telebot.types.Message:202 +#: of telebot.types.Message:208 msgid "Optional. Telegram Passport data" msgstr "" -#: of telebot.types.Message:205 +#: of telebot.types.Message:211 msgid "" "Optional. Service message. A user in the chat triggered another user's " "proximity alert while sharing Live Location." msgstr "" -#: of telebot.types.Message:209 +#: of telebot.types.Message:215 msgid "Optional. Service message: forum topic created" msgstr "" -#: of telebot.types.Message:212 +#: of telebot.types.Message:218 msgid "Optional. Service message: forum topic edited" msgstr "" -#: of telebot.types.Message:215 +#: of telebot.types.Message:221 msgid "Optional. Service message: forum topic closed" msgstr "" -#: of telebot.types.Message:218 +#: of telebot.types.Message:224 msgid "Optional. Service message: forum topic reopened" msgstr "" -#: of telebot.types.Message:221 +#: of telebot.types.Message:227 msgid "Optional. Service message: the 'General' forum topic hidden" msgstr "" -#: of telebot.types.Message:224 +#: of telebot.types.Message:230 msgid "Optional. Service message: the 'General' forum topic unhidden" msgstr "" -#: of telebot.types.Message:227 +#: of telebot.types.Message:233 msgid "Optional. Service message: video chat scheduled" msgstr "" -#: of telebot.types.Message:230 +#: of telebot.types.Message:236 msgid "Optional. Service message: video chat started" msgstr "" -#: of telebot.types.Message:233 +#: of telebot.types.Message:239 msgid "Optional. Service message: video chat ended" msgstr "" -#: of telebot.types.Message:236 +#: of telebot.types.Message:242 msgid "Optional. Service message: new participants invited to a video chat" msgstr "" -#: of telebot.types.Message:239 +#: of telebot.types.Message:245 msgid "Optional. Service message: data sent by a Web App" msgstr "" -#: of telebot.types.Message:242 +#: of telebot.types.Message:248 msgid "" "Optional. Inline keyboard attached to the message. login_url buttons are " "represented as ordinary url buttons." msgstr "" -#: of telebot.types.Message:247 +#: of telebot.types.Message:253 msgid ":class:`telebot.types.Message`" msgstr "" @@ -4540,7 +4917,7 @@ msgstr "" msgid "Photo height" msgstr "" -#: of telebot.types.PhotoSize:18 telebot.types.Sticker:46 +#: of telebot.types.PhotoSize:18 telebot.types.Sticker:51 #: telebot.types.VideoNote:21 msgid "Optional. File size in bytes" msgstr "" @@ -5058,7 +5435,14 @@ msgstr "" msgid "Optional. For custom emoji stickers, unique identifier of the custom emoji" msgstr "" -#: of telebot.types.Sticker:50 +#: of telebot.types.Sticker:46 +msgid "" +"Optional. True, if the sticker must be repainted to a text color in " +"messages, the color of the Telegram Premium badge in emoji status, white " +"color on chat photos, or another appropriate color in other places" +msgstr "" + +#: of telebot.types.Sticker:55 msgid ":class:`telebot.types.Sticker`" msgstr "" @@ -5136,6 +5520,45 @@ msgstr "" msgid ":class:`telebot.types.SuccessfulPayment`" msgstr "" +#: of telebot.types.SwitchInlineQueryChosenChat:1 telebot.types.User:1 +msgid "" +"Bases: :py:class:`telebot.types.JsonDeserializable`, " +":py:class:`telebot.types.Dictionaryable`, " +":py:class:`telebot.types.JsonSerializable`" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:1 +msgid "" +"Represents an inline button that switches the current user to inline mode" +" in a chosen chat, with an optional default inline query." +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:6 +msgid "" +"Optional. The default inline query to be inserted in the input field. If " +"left empty, only the bot's username will be inserted" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:10 +msgid "Optional. True, if private chats with users can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:13 +msgid "Optional. True, if private chats with bots can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:16 +msgid "Optional. True, if group and supergroup chats can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:19 +msgid "Optional. True, if channel chats can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:23 +msgid ":class:`SwitchInlineQueryChosenChat`" +msgstr "" + #: of telebot.types.Update:1 msgid "" "This object represents an incoming update.At most one of the optional " @@ -5240,13 +5663,6 @@ msgstr "" msgid ":class:`telebot.types.Update`" msgstr "" -#: of telebot.types.User:1 -msgid "" -"Bases: :py:class:`telebot.types.JsonDeserializable`, " -":py:class:`telebot.types.Dictionaryable`, " -":py:class:`telebot.types.JsonSerializable`" -msgstr "" - #: of telebot.types.User:1 msgid "This object represents a Telegram user or bot." msgstr "" @@ -5348,6 +5764,32 @@ msgstr "" msgid ":class:`telebot.types.UserProfilePhotos`" msgstr "" +#: of telebot.types.UserShared:1 +msgid "" +"This object contains information about the user whose identifier was " +"shared with the bot using a `telebot.types.KeyboardButtonRequestUser` " +"button." +msgstr "" + +#: of telebot.types.UserShared:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#usershared" +msgstr "" + +#: of telebot.types.UserShared:9 +msgid "" +"Identifier of the shared user. This number may have more than 32 " +"significant bits and some programming languages may have " +"difficulty/silent defects in interpreting it. But it has at most 52 " +"significant bits, so a 64-bit integer or double-precision float type are " +"safe for storing this identifier. The bot may not have access to the user" +" and could be unable to use this identifier, unless the user is already " +"known to the bot by some other means." +msgstr "" + +#: of telebot.types.UserShared:16 +msgid ":class:`telebot.types.UserShared`" +msgstr "" + #: of telebot.types.Venue:1 msgid "This object represents a venue." msgstr "" @@ -5633,6 +6075,37 @@ msgid "" "https://core.telegram.org/bots/api#writeaccessallowed" msgstr "" +#: of telebot.types.WriteAccessAllowed:6 +msgid "Optional. Name of the Web App which was launched from a link" +msgstr "" + #~ msgid "Type of the result, must be animation" #~ msgstr "" +#~ msgid "" +#~ "True, if the user is allowed to" +#~ " send audios, documents, photos, videos," +#~ " video notes and voice notes" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. True, if the user is " +#~ "allowed to send audios, documents, " +#~ "photos, videos, video notes and voice" +#~ " notes, implies can_send_messages" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. True, if the user is " +#~ "allowed to send animations, games, " +#~ "stickers and use inline bots, implies" +#~ " can_send_media_messages" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. True, if the user is " +#~ "allowed to add web page previews " +#~ "to their messages, implies " +#~ "can_send_media_messages" +#~ msgstr "" + diff --git a/docs/source/locales/en/LC_MESSAGES/util.po b/docs/source/locales/en/LC_MESSAGES/util.po index afba83905..0d5f4b500 100644 --- a/docs/source/locales/en/LC_MESSAGES/util.po +++ b/docs/source/locales/en/LC_MESSAGES/util.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-29 14:44+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,19 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.9.1\n" -#: ../../util.rst:3 +#: ../../source/util.rst:3 msgid "Utils" msgstr "" -#: ../../util.rst:5 +#: ../../source/util.rst:5 msgid "Utils in pyTelegramBotAPI" msgstr "" -#: ../../util.rst:5 +#: ../../source/util.rst:5 msgid "ptba, pytba, pyTelegramBotAPI, utils, guide" msgstr "" -#: ../../util.rst:11 +#: ../../source/util.rst:11 msgid "util file" msgstr "" @@ -40,9 +40,10 @@ msgid "" "error. Example:" msgstr "" -#: of telebot.util.antiflood telebot.util.escape telebot.util.extract_arguments -#: telebot.util.extract_command telebot.util.is_bytes telebot.util.is_command -#: telebot.util.is_dict telebot.util.is_pil_image +#: of telebot.service_utils.is_bytes telebot.service_utils.is_dict +#: telebot.service_utils.is_pil_image telebot.util.antiflood +#: telebot.util.escape telebot.util.extract_arguments +#: telebot.util.extract_command telebot.util.is_command #: telebot.util.parse_web_app_data telebot.util.quick_markup #: telebot.util.smart_split telebot.util.split_string telebot.util.user_link #: telebot.util.validate_web_app_data telebot.util.webhook_google_functions @@ -54,28 +55,33 @@ msgid "The function to call" msgstr "" #: of telebot.util.antiflood:13 -msgid "The arguments to pass to the function" +msgid "Number of retries to send" msgstr "" #: of telebot.util.antiflood:16 +msgid "The arguments to pass to the function" +msgstr "" + +#: of telebot.util.antiflood:19 msgid "The keyword arguments to pass to the function" msgstr "" -#: of telebot.util.antiflood telebot.util.escape telebot.util.extract_arguments -#: telebot.util.extract_command telebot.util.generate_random_token -#: telebot.util.is_bytes telebot.util.is_command telebot.util.is_dict -#: telebot.util.is_pil_image telebot.util.parse_web_app_data -#: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string -#: telebot.util.user_link telebot.util.validate_web_app_data -#: telebot.util.webhook_google_functions +#: of telebot.service_utils.generate_random_token +#: telebot.service_utils.is_bytes telebot.service_utils.is_dict +#: telebot.service_utils.is_pil_image telebot.util.antiflood +#: telebot.util.escape telebot.util.extract_arguments +#: telebot.util.extract_command telebot.util.is_command +#: telebot.util.parse_web_app_data telebot.util.quick_markup +#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link +#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions msgid "Returns" msgstr "" -#: of telebot.util.antiflood:19 +#: of telebot.util.antiflood:22 msgid "None" msgstr "" -#: of telebot.util.chunks:1 +#: of telebot.service_utils.chunks:1 msgid "Yield successive n-sized chunks from lst." msgstr "" @@ -117,9 +123,10 @@ msgstr "" msgid "the arguments if `text` is a command (according to is_command), else None." msgstr "" -#: of telebot.util.extract_arguments telebot.util.extract_command -#: telebot.util.generate_random_token telebot.util.is_bytes -#: telebot.util.is_command telebot.util.is_dict telebot.util.is_pil_image +#: of telebot.service_utils.generate_random_token +#: telebot.service_utils.is_bytes telebot.service_utils.is_dict +#: telebot.service_utils.is_pil_image telebot.util.extract_arguments +#: telebot.util.extract_command telebot.util.is_command #: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string #: telebot.util.user_link msgid "Return type" @@ -143,35 +150,35 @@ msgstr "" msgid "the command if `text` is a command (according to is_command), else None." msgstr "" -#: of telebot.util.generate_random_token:1 +#: of telebot.service_utils.generate_random_token:1 msgid "" "Generates a random token consisting of letters and digits, 16 characters " "long." msgstr "" -#: of telebot.util.generate_random_token:3 +#: of telebot.service_utils.generate_random_token:3 msgid "a random token" msgstr "" -#: of telebot.util.generate_random_token:4 telebot.util.user_link:22 +#: of telebot.service_utils.generate_random_token:4 telebot.util.user_link:22 msgid ":obj:`str`" msgstr "" -#: of telebot.util.is_bytes:1 +#: of telebot.service_utils.is_bytes:1 msgid "Returns True if the given object is a bytes object." msgstr "" -#: of telebot.util.is_bytes:3 telebot.util.is_dict:3 -#: telebot.util.is_pil_image:3 +#: of telebot.service_utils.is_bytes:3 telebot.service_utils.is_dict:3 +#: telebot.service_utils.is_pil_image:3 msgid "object to be checked" msgstr "" -#: of telebot.util.is_bytes:6 +#: of telebot.service_utils.is_bytes:6 msgid "True if the given object is a bytes object." msgstr "" -#: of telebot.util.is_bytes:7 telebot.util.is_command:7 telebot.util.is_dict:7 -#: telebot.util.is_pil_image:7 +#: of telebot.service_utils.is_bytes:7 telebot.service_utils.is_dict:7 +#: telebot.service_utils.is_pil_image:7 telebot.util.is_command:7 msgid ":obj:`bool`" msgstr "" @@ -189,23 +196,23 @@ msgstr "" msgid "True if `text` is a command, else False." msgstr "" -#: of telebot.util.is_dict:1 +#: of telebot.service_utils.is_dict:1 msgid "Returns True if the given object is a dictionary." msgstr "" -#: of telebot.util.is_dict:6 +#: of telebot.service_utils.is_dict:6 msgid "True if the given object is a dictionary." msgstr "" -#: of telebot.util.is_pil_image:1 +#: of telebot.service_utils.is_pil_image:1 msgid "Returns True if the given object is a PIL.Image.Image object." msgstr "" -#: of telebot.util.is_pil_image:6 +#: of telebot.service_utils.is_pil_image:6 msgid "True if the given object is a PIL.Image.Image object." msgstr "" -#: of telebot.util.is_string:1 +#: of telebot.service_utils.is_string:1 msgid "Returns True if the given object is a string." msgstr "" @@ -240,21 +247,21 @@ msgstr "" msgid "Using quick_markup:" msgstr "" -#: of telebot.util.quick_markup:29 +#: of telebot.util.quick_markup:31 msgid "" "a dict containing all buttons to create in this format: {text: kwargs} " "{str:}" msgstr "" -#: of telebot.util.quick_markup:32 -msgid "int row width" +#: of telebot.util.quick_markup:34 +msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row" msgstr "" -#: of telebot.util.quick_markup:35 +#: of telebot.util.quick_markup:37 msgid "InlineKeyboardMarkup" msgstr "" -#: of telebot.util.quick_markup:36 +#: of telebot.util.quick_markup:38 msgid ":obj:`types.InlineKeyboardMarkup`" msgstr "" @@ -343,3 +350,6 @@ msgstr "" msgid "The response object" msgstr "" +#~ msgid "int row width" +#~ msgstr "" + diff --git a/docs/source/locales/ru/LC_MESSAGES/async_version.po b/docs/source/locales/ru/LC_MESSAGES/async_version.po index 86d86bfb8..8644f09fb 100644 --- a/docs/source/locales/ru/LC_MESSAGES/async_version.po +++ b/docs/source/locales/ru/LC_MESSAGES/async_version.po @@ -4,13 +4,12 @@ # Documentation package. # FIRST AUTHOR , 2022. # - #, fuzzy msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-02 19:24+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -108,6 +107,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_webhook #: telebot.async_telebot.AsyncTeleBot.download_file #: telebot.async_telebot.AsyncTeleBot.edit_chat_invite_link @@ -134,6 +134,9 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.get_game_high_scores #: telebot.async_telebot.AsyncTeleBot.get_my_commands #: telebot.async_telebot.AsyncTeleBot.get_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.get_my_description +#: telebot.async_telebot.AsyncTeleBot.get_my_name +#: telebot.async_telebot.AsyncTeleBot.get_my_short_description #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates @@ -199,12 +202,20 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.set_chat_photo #: telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.set_chat_title +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.set_my_description +#: telebot.async_telebot.AsyncTeleBot.set_my_name +#: telebot.async_telebot.AsyncTeleBot.set_my_short_description #: telebot.async_telebot.AsyncTeleBot.set_state +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title #: telebot.async_telebot.AsyncTeleBot.set_update_listener #: telebot.async_telebot.AsyncTeleBot.set_webhook #: telebot.async_telebot.AsyncTeleBot.setup_middleware @@ -223,7 +234,6 @@ msgid "Parameters" msgstr "" #: of telebot.async_telebot.AsyncTeleBot:24 - msgid "Token of a bot, obtained from @BotFather" msgstr "Токен бота, нужно получить от @BotFather" @@ -308,6 +318,7 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_webhook #: telebot.async_telebot.AsyncTeleBot.download_file #: telebot.async_telebot.AsyncTeleBot.edit_chat_invite_link @@ -333,6 +344,9 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.get_game_high_scores #: telebot.async_telebot.AsyncTeleBot.get_my_commands #: telebot.async_telebot.AsyncTeleBot.get_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.get_my_description +#: telebot.async_telebot.AsyncTeleBot.get_my_name +#: telebot.async_telebot.AsyncTeleBot.get_my_short_description #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates @@ -396,12 +410,20 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.set_chat_photo #: telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.set_chat_title +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.set_my_description +#: telebot.async_telebot.AsyncTeleBot.set_my_name +#: telebot.async_telebot.AsyncTeleBot.set_my_short_description #: telebot.async_telebot.AsyncTeleBot.set_state +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title #: telebot.async_telebot.AsyncTeleBot.set_update_listener #: telebot.async_telebot.AsyncTeleBot.set_webhook #: telebot.async_telebot.AsyncTeleBot.setup_middleware @@ -481,36 +503,45 @@ msgstr "Данные для добавления" #: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:1 msgid "" -"Use this method to add a new sticker to a set created by the bot. It's " -"required to pass `png_sticker` or `tgs_sticker`. Returns True on success." +"Use this method to add a new sticker to a set created by the bot. The " +"format of the added sticker must match the format of the other stickers " +"in the set. Emoji sticker sets can have up to 200 stickers. Animated and " +"video sticker sets can have up to 50 stickers. Static sticker sets can " +"have up to 120 stickers. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:8 +msgid "" +"**_sticker, mask_position, emojis parameters are deprecated, use stickers" +" instead" msgstr "" -"Используйте этот метод, чтобы добавить новый стикер в стикерпак, " -"созданный ботом. Необходимо передать либо `png_sticker`, либо " -"`tgs_sticker`, либо `webm_sticker`. Возвращает True в случае успешного " -"добавления." -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:5 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:10 msgid "Telegram documentation: https://core.telegram.org/bots/api#addstickertoset" msgstr "Документация Telegram: https://core.telegram.org/bots/api#addstickertoset" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:7 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:7 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:12 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:10 msgid "User identifier of created sticker set owner" msgstr "id пользователя, создавшего стикерпак" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:10 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:15 +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:3 #: telebot.async_telebot.AsyncTeleBot.get_sticker_set:5 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:6 +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:4 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:4 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:6 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:4 msgid "Sticker set name" msgstr "Имя стикерпака" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:13 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:18 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:18 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:21 msgid "One or more emoji corresponding to the sticker" msgstr "Один или несколько эмодзи, относящихся к стикеру" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:16 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:21 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:21 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:24 msgid "" "PNG image with the sticker, must be up to 512 kilobytes in size, " "dimensions must not exceed 512px, and either width or height must be " @@ -526,40 +557,47 @@ msgstr "" "Telegram скачал файл из интернета, или загрузите новый файл с помощью " "multipart/form-data." -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:21 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:26 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:26 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:29 msgid "TGS animation with the sticker, uploaded using multipart/form-data." msgstr "" "Анимированный стикер в формате TGS, загруженный с помощью multipart/form-" "data." -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:24 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:29 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:29 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:32 msgid "WebM animation with the sticker, uploaded using multipart/form-data." msgstr "" "Анимированный стикер в формате WebM, загруженный с помощью multipart" "/form-data." -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:27 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:40 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:32 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:42 msgid "" "A JSON-serialized object for position where the mask should be placed on " "faces" msgstr "Позиция для размещения маски на лицах в формате JSON" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:30 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:35 +msgid "" +"A JSON-serialized list of 1-50 initial stickers to be added to the " +"sticker set" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:38 #: telebot.async_telebot.AsyncTeleBot.answer_callback_query:22 -#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:35 +#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:38 #: telebot.async_telebot.AsyncTeleBot.answer_pre_checkout_query:21 #: telebot.async_telebot.AsyncTeleBot.answer_shipping_query:18 #: telebot.async_telebot.AsyncTeleBot.close_forum_topic:13 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:43 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:56 #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic:13 #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set:6 #: telebot.async_telebot.AsyncTeleBot.edit_forum_topic:22 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:13 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:11 #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:11 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:15 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:13 msgid "On success, True is returned." msgstr "В случае успеха возвращается True." @@ -586,6 +624,7 @@ msgstr "В случае успеха возвращается True." #: telebot.async_telebot.AsyncTeleBot.delete_message #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_webhook #: telebot.async_telebot.AsyncTeleBot.download_file #: telebot.async_telebot.AsyncTeleBot.edit_chat_invite_link @@ -645,11 +684,16 @@ msgstr "В случае успеха возвращается True." #: telebot.async_telebot.AsyncTeleBot.set_chat_photo #: telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.set_chat_title +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title #: telebot.async_telebot.AsyncTeleBot.set_webhook #: telebot.async_telebot.AsyncTeleBot.stop_message_live_location #: telebot.async_telebot.AsyncTeleBot.stop_poll @@ -662,9 +706,9 @@ msgstr "В случае успеха возвращается True." msgid "Return type" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:31 +#: of telebot.async_telebot.AsyncTeleBot.add_sticker_to_set:39 #: telebot.async_telebot.AsyncTeleBot.answer_callback_query:23 -#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:36 +#: telebot.async_telebot.AsyncTeleBot.answer_inline_query:39 #: telebot.async_telebot.AsyncTeleBot.answer_pre_checkout_query:22 #: telebot.async_telebot.AsyncTeleBot.answer_shipping_query:19 #: telebot.async_telebot.AsyncTeleBot.approve_chat_join_request:15 @@ -672,7 +716,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat:17 #: telebot.async_telebot.AsyncTeleBot.close:9 #: telebot.async_telebot.AsyncTeleBot.close_forum_topic:14 -#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:44 +#: telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:57 #: telebot.async_telebot.AsyncTeleBot.decline_chat_join_request:15 #: telebot.async_telebot.AsyncTeleBot.delete_chat_photo:13 #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set:11 @@ -680,6 +724,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_message:23 #: telebot.async_telebot.AsyncTeleBot.delete_my_commands:17 #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set:7 +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:7 #: telebot.async_telebot.AsyncTeleBot.delete_webhook:13 #: telebot.async_telebot.AsyncTeleBot.edit_forum_topic:23 #: telebot.async_telebot.AsyncTeleBot.leave_chat:8 @@ -687,18 +732,23 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:19 #: telebot.async_telebot.AsyncTeleBot.promote_chat_member:61 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:14 -#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:48 +#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:61 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:26 #: telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:18 #: telebot.async_telebot.AsyncTeleBot.set_chat_description:14 #: telebot.async_telebot.AsyncTeleBot.set_chat_menu_button:15 -#: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:15 +#: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:21 #: telebot.async_telebot.AsyncTeleBot.set_chat_photo:16 #: telebot.async_telebot.AsyncTeleBot.set_chat_title:17 +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:11 #: telebot.async_telebot.AsyncTeleBot.set_my_commands:18 #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:18 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:11 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:12 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:12 #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:12 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:16 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:16 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:11 #: telebot.async_telebot.AsyncTeleBot.unban_chat_member:20 #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:12 @@ -854,6 +904,13 @@ msgstr "" "Параметр для передачи боту вместе с сообщением /start, отправленному при " "нажатии кнопки переключения" +#: of telebot.async_telebot.AsyncTeleBot.answer_inline_query:35 +#, fuzzy +msgid "" +"A JSON-serialized object describing a button to be shown above inline " +"query results" +msgstr "Объект в формате JSON, описывающий сообщение, которое нужно отправить" + #: of telebot.async_telebot.AsyncTeleBot.answer_pre_checkout_query:1 msgid "" "Once the user has confirmed their payment and shipping details, the Bot " @@ -1019,7 +1076,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_chat_member:8 #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:6 #: telebot.async_telebot.AsyncTeleBot.promote_chat_member:11 -#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:11 +#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:14 #: telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:10 #: telebot.async_telebot.AsyncTeleBot.unban_chat_member:13 msgid "Unique identifier of the target user" @@ -1040,6 +1097,9 @@ msgstr "Уникальный id сделавшего запрос пользов #: telebot.async_telebot.AsyncTeleBot.set_chat_title:16 #: telebot.async_telebot.AsyncTeleBot.set_my_commands:17 #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:17 +#: telebot.async_telebot.AsyncTeleBot.set_my_description:12 +#: telebot.async_telebot.AsyncTeleBot.set_my_name:12 +#: telebot.async_telebot.AsyncTeleBot.set_my_short_description:12 #: telebot.async_telebot.AsyncTeleBot.set_webhook:46 #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:14 #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:11 @@ -1064,7 +1124,7 @@ msgid "Telegram documentation: https://core.telegram.org/bots/api#banchatmember" msgstr "Документация Telegram: https://core.telegram.org/bots/api#banchatmember" #: of telebot.async_telebot.AsyncTeleBot.ban_chat_member:8 -#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:7 +#: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:10 msgid "" "Unique identifier for the target group or username of the target " "supergroup or channel (in the format @channelusername)" @@ -1096,8 +1156,13 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.ban_chat_member:24 #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set:10 #: telebot.async_telebot.AsyncTeleBot.delete_message:22 +#: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:6 #: telebot.async_telebot.AsyncTeleBot.delete_webhook:12 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:25 +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:10 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:10 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:11 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:10 msgid "Returns True on success." msgstr "Возвращает True в случае успеха." @@ -1297,7 +1362,6 @@ msgstr "" "декорируемую функцию объект :class:`telebot.types.ChatMemberUpdated`." #: of telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:1 - msgid "" "The result of an inline query that was chosen by a user and sent to their" " chat partner. Please see our documentation on the feedback collecting " @@ -1350,7 +1414,6 @@ msgid "Identifier of the topic to close" msgstr "id топика для закрытия" #: of telebot.async_telebot.AsyncTeleBot.close_general_forum_topic:1 - msgid "" "Use this method to close the 'General' topic in a forum supergroup chat. " "The bot must be an administrator in the chat for this to work and must " @@ -1362,7 +1425,6 @@ msgstr "" "топика. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.close_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#closegeneralforumtopic" @@ -1561,21 +1623,21 @@ msgstr "id топика, в который нужно отправить соо #: of telebot.async_telebot.AsyncTeleBot.copy_message:45 #: telebot.async_telebot.AsyncTeleBot.forward_message:26 #: telebot.async_telebot.AsyncTeleBot.reply_to:11 -#: telebot.async_telebot.AsyncTeleBot.send_animation:63 -#: telebot.async_telebot.AsyncTeleBot.send_audio:63 +#: telebot.async_telebot.AsyncTeleBot.send_animation:66 +#: telebot.async_telebot.AsyncTeleBot.send_audio:66 #: telebot.async_telebot.AsyncTeleBot.send_contact:44 #: telebot.async_telebot.AsyncTeleBot.send_dice:35 -#: telebot.async_telebot.AsyncTeleBot.send_document:56 +#: telebot.async_telebot.AsyncTeleBot.send_document:59 #: telebot.async_telebot.AsyncTeleBot.send_game:32 #: telebot.async_telebot.AsyncTeleBot.send_invoice:101 #: telebot.async_telebot.AsyncTeleBot.send_location:49 #: telebot.async_telebot.AsyncTeleBot.send_message:46 #: telebot.async_telebot.AsyncTeleBot.send_photo:48 #: telebot.async_telebot.AsyncTeleBot.send_poll:70 -#: telebot.async_telebot.AsyncTeleBot.send_sticker:39 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:42 #: telebot.async_telebot.AsyncTeleBot.send_venue:57 -#: telebot.async_telebot.AsyncTeleBot.send_video:64 -#: telebot.async_telebot.AsyncTeleBot.send_video_note:48 +#: telebot.async_telebot.AsyncTeleBot.send_video:67 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:51 #: telebot.async_telebot.AsyncTeleBot.send_voice:49 msgid "On success, the sent Message is returned." msgstr "В случае успеха возвращает отправленное сообщение (Message)." @@ -1583,18 +1645,18 @@ msgstr "В случае успеха возвращает отправленно #: of telebot.async_telebot.AsyncTeleBot.copy_message:46 #: telebot.async_telebot.AsyncTeleBot.forward_message:27 #: telebot.async_telebot.AsyncTeleBot.reply_to:12 -#: telebot.async_telebot.AsyncTeleBot.send_animation:64 -#: telebot.async_telebot.AsyncTeleBot.send_audio:64 +#: telebot.async_telebot.AsyncTeleBot.send_animation:67 +#: telebot.async_telebot.AsyncTeleBot.send_audio:67 #: telebot.async_telebot.AsyncTeleBot.send_contact:45 #: telebot.async_telebot.AsyncTeleBot.send_dice:36 -#: telebot.async_telebot.AsyncTeleBot.send_document:57 +#: telebot.async_telebot.AsyncTeleBot.send_document:60 #: telebot.async_telebot.AsyncTeleBot.send_location:50 #: telebot.async_telebot.AsyncTeleBot.send_message:47 #: telebot.async_telebot.AsyncTeleBot.send_photo:49 -#: telebot.async_telebot.AsyncTeleBot.send_sticker:40 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:43 #: telebot.async_telebot.AsyncTeleBot.send_venue:58 -#: telebot.async_telebot.AsyncTeleBot.send_video:65 -#: telebot.async_telebot.AsyncTeleBot.send_video_note:49 +#: telebot.async_telebot.AsyncTeleBot.send_video:68 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:52 msgid ":class:`telebot.types.Message`" msgstr "" @@ -1606,10 +1668,11 @@ msgid "" "method revokeChatInviteLink. Returns the new invite link as " "ChatInviteLink object." msgstr "" -"Используйте этот метод, чтобы создать дополнительную ссылку-приглашение в чат. Бот " -"должен быть администратором чата и иметь соответствующие права администратора. " -"Ссылка может быть аннулирована методом revokeChatInviteLink. Возвращает новую " -"ссылку-приглашение (ChatInviteLink)." +"Используйте этот метод, чтобы создать дополнительную ссылку-приглашение в" +" чат. Бот должен быть администратором чата и иметь соответствующие права " +"администратора. Ссылка может быть аннулирована методом " +"revokeChatInviteLink. Возвращает новую ссылку-приглашение " +"(ChatInviteLink)." #: of telebot.async_telebot.AsyncTeleBot.create_chat_invite_link:6 msgid "" @@ -1893,7 +1956,13 @@ msgstr "" "Документация Telegram: " "https://core.telegram.org/bots/api#createnewstickerset" -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:10 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:8 +msgid "" +"Fields *_sticker are deprecated, pass a list of stickers to stickers " +"parameter instead." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:13 msgid "" "Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., " "animals). Can contain only English letters, digits and underscores. Must " @@ -1907,11 +1976,11 @@ msgstr "" "содержать подряд идущие нижние подчеркивания и должно заканчиваться на " "\"_by_\". учитывает регистр. 1-64 символа." -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:15 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:18 msgid "Sticker set title, 1-64 characters" msgstr "Название стикерпака, 1-64 символа" -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:32 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:35 msgid "" "Pass True, if a set of mask stickers should be created. Deprecated since " "Bot API 6.2, use sticker_type instead." @@ -1919,16 +1988,34 @@ msgstr "" "Передайте True, если создаётся стикерпак масок. Устарело, начиная с Bot " "API 6.2, используйте sticker_type." -#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:36 +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:39 +#, fuzzy msgid "" -"Optional, Type of stickers in the set, pass “regular” or “mask”. Custom " -"emoji sticker sets can't be created via the Bot API at the moment. By " -"default, a regular sticker set is created." +"Type of stickers in the set, pass “regular”, “mask”, or “custom_emoji”. " +"By default, a regular sticker set is created." msgstr "" "Необязательный, тип стикерпака, передайте “regular” или “mask”. " "Стикерпаки кастомных эмодзи пока что не могут быть созданы с помощью Bot " "API. По умолчанию будет создан обычный стикерпак." +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:45 +msgid "" +"Pass True if stickers in the sticker set must be repainted to the color " +"of text when used in messages, the accent color if used as emoji status, " +"white on chat photos, or another appropriate color based on context; for " +"custom emoji sticker sets only" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:50 +msgid "List of stickers to be added to the set" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.create_new_sticker_set:53 +msgid "" +"Format of stickers in the set, must be one of “static”, “animated”, " +"“video”" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.decline_chat_join_request:1 msgid "" "Use this method to decline a chat join request. The bot must be an " @@ -2112,6 +2199,13 @@ msgstr "" msgid "File identifier of the sticker" msgstr "id файла стикера" +#: of telebot.async_telebot.AsyncTeleBot.delete_sticker_set:1 +#, fuzzy +msgid "Use this method to delete a sticker set. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы удалить стикер из стикерпака, созданного " +"ботом. Возвращает True в случае успеха." + #: of telebot.async_telebot.AsyncTeleBot.delete_webhook:1 msgid "" "Use this method to remove webhook integration if you decide to switch " @@ -2198,8 +2292,8 @@ msgid "" "Optional, New name of the topic, 1-128 characters. If not specififed or " "empty, the current name of the topic will be kept" msgstr "" -"Необязательный, новое имя топика, 1-128 символов. Если не задано или пустое, " -"сохранится текущее имя топика" +"Необязательный, новое имя топика, 1-128 символов. Если не задано или " +"пустое, сохранится текущее имя топика" #: of telebot.async_telebot.AsyncTeleBot.edit_forum_topic:17 msgid "" @@ -2214,7 +2308,6 @@ msgstr "" "чтобы убрать иконку. Если не задан, сохранится текущая иконка топика" #: of telebot.async_telebot.AsyncTeleBot.edit_general_forum_topic:1 - msgid "" "Use this method to edit the name of the 'General' topic in a forum " "supergroup chat. The bot must be an administrator in the chat for this to" @@ -2227,14 +2320,12 @@ msgstr "" "True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.edit_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#editgeneralforumtopic" msgstr "Документация Telegram: https://core.telegram.org/bots/api#editforumtopic" #: of telebot.async_telebot.AsyncTeleBot.edit_general_forum_topic:10 - msgid "New topic name, 1-128 characters" msgstr "Название товара, 1-32 символа" @@ -2320,9 +2411,9 @@ msgid "" "message is not an inline message, the edited Message is returned, " "otherwise True is returned." msgstr "" -"отключено вызовом метода stopMessageLiveLocation. В случае успеха, если измененное " -"сообщение не является inline сообщением, возвращается новый объект Message, " -"иначе возвращается True." +"отключено вызовом метода stopMessageLiveLocation. В случае успеха, если " +"измененное сообщение не является inline сообщением, возвращается новый " +"объект Message, иначе возвращается True." #: of telebot.async_telebot.AsyncTeleBot.edit_message_live_location:5 msgid "" @@ -2432,8 +2523,8 @@ msgid "" " target chat or username of the target channel (in the format " "@channelusername)" msgstr "" -"Обязательный, если не указан inline_message_id. Уникальный id чата " -"или username канала (в формате @channelusername)" +"Обязательный, если не указан inline_message_id. Уникальный id чата или " +"username канала (в формате @channelusername)" #: of telebot.async_telebot.AsyncTeleBot.edit_message_media:13 #: telebot.async_telebot.AsyncTeleBot.edit_message_reply_markup:8 @@ -2443,8 +2534,7 @@ msgstr "" msgid "" "Required if inline_message_id is not specified. Identifier of the sent " "message" -msgstr "" -"Обязательный, если не указан inline_message_id. id отправленного сообщения" +msgstr "Обязательный, если не указан inline_message_id. id отправленного сообщения" #: of telebot.async_telebot.AsyncTeleBot.edit_message_media:23 #: telebot.async_telebot.AsyncTeleBot.edit_message_reply_markup:18 @@ -2487,8 +2577,8 @@ msgid "" "List of special entities that appear in the message text, which can be " "specified instead of parse_mode" msgstr "" -"Список отформатированных частей в тексте сообщения, " -"можно использовать вместо parse_mode" +"Список отформатированных частей в тексте сообщения, можно использовать " +"вместо parse_mode" #: of telebot.async_telebot.AsyncTeleBot.edit_message_text:23 #: telebot.async_telebot.AsyncTeleBot.send_message:21 @@ -2501,13 +2591,15 @@ msgid "" "edited. As a parameter to the decorator function, it passes " ":class:`telebot.types.Message` object." msgstr "" -"Обрабатывает новую версию поста в канале, который доступен боту и был изменён. " -"В качестве параметра, передаёт в декорируемую функцию объект " +"Обрабатывает новую версию поста в канале, который доступен боту и был " +"изменён. В качестве параметра, передаёт в декорируемую функцию объект " ":class:`telebot.types.Message`." #: of telebot.async_telebot.AsyncTeleBot.edited_message_handler:1 msgid "Handles new version of a message that is known to the bot and was edited." -msgstr "Обрабатывает новую версию сообщения, которое доступно боту и было изменено." +msgstr "" +"Обрабатывает новую версию сообщения, которое доступно боту и было " +"изменено." #: of telebot.async_telebot.AsyncTeleBot.edited_message_handler:3 msgid "" @@ -2532,8 +2624,9 @@ msgid "" ":class:`~telebot.asyncio_storage.StatePickleStorage` instance as " "state_storage to TeleBot class." msgstr "" -"Рекомендуется передавать экземпляр класса :class:`~telebot.storage.StatePickleStorage` " -"в качестве state_storage при инициализации класса TeleBot вместо использования этой функции." +"Рекомендуется передавать экземпляр класса " +":class:`~telebot.storage.StatePickleStorage` в качестве state_storage при" +" инициализации класса TeleBot вместо использования этой функции." #: of telebot.async_telebot.AsyncTeleBot.enable_saving_states:7 msgid "Filename of saving file, defaults to \"./.state-save/states.pkl\"" @@ -2545,9 +2638,9 @@ msgid "" "The bot must be an administrator in the chat for this to work and must " "have the appropriate admin rights." msgstr "" -"Используйте этот метод, чтобы создать или заменить главную ссылку-приглашение " -"в супергруппу или канал, созданную ботом. Бот должен быть администратором чата " -"и иметь соответствующие права администратора." +"Используйте этот метод, чтобы создать или заменить главную " +"ссылку-приглашение в супергруппу или канал, созданную ботом. Бот должен " +"быть администратором чата и иметь соответствующие права администратора." #: of telebot.async_telebot.AsyncTeleBot.export_chat_invite_link:4 msgid "" @@ -2596,9 +2689,10 @@ msgid "" "name of the user for one-on-one conversations, current username of a " "user, group or channel, etc.). Returns a Chat object on success." msgstr "" -"Используйте этот метод, чтобы получить актуальную информацию о чате (текущее " -"имя пользователя для персональных диалогов, текущий username пользователя, " -"группы или канала и т.д.). В случае успеха возвращает объект Chat." +"Используйте этот метод, чтобы получить актуальную информацию о чате " +"(текущее имя пользователя для персональных диалогов, текущий username " +"пользователя, группы или канала и т.д.). В случае успеха возвращает " +"объект Chat." #: of telebot.async_telebot.AsyncTeleBot.get_chat:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#getchat" @@ -2612,8 +2706,8 @@ msgid "" "Unique identifier for the target chat or username of the target " "supergroup or channel (in the format @channelusername)" msgstr "" -"Уникальный id чата или username супергруппы или канала " -"(в формате @channelusername)" +"Уникальный id чата или username супергруппы или канала (в формате " +"@channelusername)" #: of telebot.async_telebot.AsyncTeleBot.get_chat:9 msgid "Chat information" @@ -2629,9 +2723,9 @@ msgid "" "returns an Array of ChatMember objects that contains information about " "all chat administrators except other bots." msgstr "" -"Используйте этот метод, чтобы получить список администраторов чата. " -"В случае успеха, возвращает массив объектов ChatMember, содержащих информацию " -"обо всех администраторах чата, кроме других ботов." +"Используйте этот метод, чтобы получить список администраторов чата. В " +"случае успеха, возвращает массив объектов ChatMember, содержащих " +"информацию обо всех администраторах чата, кроме других ботов." #: of telebot.async_telebot.AsyncTeleBot.get_chat_administrators:5 msgid "" @@ -2654,8 +2748,8 @@ msgid "" "Use this method to get information about a member of a chat. Returns a " "ChatMember object on success." msgstr "" -"Используйте этот метод, чтобы получить информацию об участнике чата. Возвращает " -"объект ChatMember в случае успеха." +"Используйте этот метод, чтобы получить информацию об участнике чата. " +"Возвращает объект ChatMember в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.get_chat_member:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#getchatmember" @@ -2695,7 +2789,8 @@ msgid "" "private chat, or the default menu button. Returns MenuButton on success." msgstr "" "Используйте этот метод, чтобы получить текущее значение кнопки menu в " -"приватном чате, или кнопку menu по умолчанию. Возвращает MenuButton в случае успеха." +"приватном чате, или кнопку menu по умолчанию. Возвращает MenuButton в " +"случае успеха." #: of telebot.async_telebot.AsyncTeleBot.get_chat_menu_button:5 msgid "" @@ -2710,8 +2805,8 @@ msgid "" "Unique identifier for the target private chat. If not specified, default " "bot's menu button will be returned." msgstr "" -"Уникальный id приватного чата. Если не указан, будет возвращена " -"кнопка menu по умолчанию." +"Уникальный id приватного чата. Если не указан, будет возвращена кнопка " +"menu по умолчанию." #: of telebot.async_telebot.AsyncTeleBot.get_chat_menu_button:11 msgid "types.MenuButton" @@ -2726,15 +2821,14 @@ msgid "" "Use this method to get information about custom emoji stickers by their " "identifiers. Returns an Array of Sticker objects." msgstr "" -"Используйте этот метод, чтобы получить информацию о кастомных эмодзи по их " -"id. Возвращает массив объектов Sticker." +"Используйте этот метод, чтобы получить информацию о кастомных эмодзи по " +"их id. Возвращает массив объектов Sticker." #: of telebot.async_telebot.AsyncTeleBot.get_custom_emoji_stickers:4 msgid "" "List of custom emoji identifiers. At most 200 custom emoji identifiers " "can be specified." -msgstr "" -"Список id кастомных эмодзи. Можно указать не более 200 id." +msgstr "Список id кастомных эмодзи. Можно указать не более 200 id." #: of telebot.async_telebot.AsyncTeleBot.get_custom_emoji_stickers:7 msgid "Returns an Array of Sticker objects." @@ -2752,11 +2846,12 @@ msgid "" "link will be valid for at least 1 hour. When the link expires, a new one " "can be requested by calling get_file again." msgstr "" -"Используйте этот метод, чтобы получить базовую информацию о файле и подготовить " -"его к скачиванию. На текущий момент, боты могут скачивать файлы весом до 20MB. " -"В случае успеха, возвращается объект File. Гарантируется, что ссылка на скачивание " -"будет актуальна как минимум 1 час. Когда ссылка перестаёт быть актуальной, новая " -"может быть снова запрошена с помощью get_file." +"Используйте этот метод, чтобы получить базовую информацию о файле и " +"подготовить его к скачиванию. На текущий момент, боты могут скачивать " +"файлы весом до 20MB. В случае успеха, возвращается объект File. " +"Гарантируется, что ссылка на скачивание будет актуальна как минимум 1 " +"час. Когда ссылка перестаёт быть актуальной, новая может быть снова " +"запрошена с помощью get_file." #: of telebot.async_telebot.AsyncTeleBot.get_file:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#getfile" @@ -2767,7 +2862,7 @@ msgid "File identifier" msgstr "id файла" #: of telebot.async_telebot.AsyncTeleBot.get_file:12 -#: telebot.async_telebot.AsyncTeleBot.upload_sticker_file:14 +#: telebot.async_telebot.AsyncTeleBot.upload_sticker_file:21 msgid ":class:`telebot.types.File`" msgstr "" @@ -2789,9 +2884,9 @@ msgid "" "forum topic icon by any user. Requires no parameters. Returns an Array of" " Sticker objects." msgstr "" -"Используйте этот метод, чтобы получить кастомные эмодзи, которые могут быть " -"использованы любыми пользователями в качестве иконок топиков. Не требует параметров. " -"Возвращает массив объектов Sticker." +"Используйте этот метод, чтобы получить кастомные эмодзи, которые могут " +"быть использованы любыми пользователями в качестве иконок топиков. Не " +"требует параметров. Возвращает массив объектов Sticker." #: of telebot.async_telebot.AsyncTeleBot.get_forum_topic_icon_stickers:4 msgid "" @@ -2815,9 +2910,9 @@ msgid "" "of the specified user and several of their neighbors in a game. On " "success, returns an Array of GameHighScore objects." msgstr "" -"Используйте этот метод, чтобы получить данные для таблицы рекордов. Вернёт " -"очки указанного пользователя и несколько соседних результатов. В случае успеха, " -"возвращает массив объектов GameHighScore." +"Используйте этот метод, чтобы получить данные для таблицы рекордов. " +"Вернёт очки указанного пользователя и несколько соседних результатов. В " +"случае успеха, возвращает массив объектов GameHighScore." #: of telebot.async_telebot.AsyncTeleBot.get_game_high_scores:4 msgid "" @@ -2826,10 +2921,10 @@ msgid "" "users if the user and their neighbors are not among them. Please note " "that this behavior is subject to change." msgstr "" -"На текущий момент этот метод вернёт очки указанного пользователя и по два соседних " -"результата с каждой стороны. Также вернет результаты трёх лучших игроков, если " -"результат пользователя и соседние не являются тремя лучшими. Пожалуйста учитывайте, " -"что это поведение может быть изменено." +"На текущий момент этот метод вернёт очки указанного пользователя и по два" +" соседних результата с каждой стороны. Также вернет результаты трёх " +"лучших игроков, если результат пользователя и соседние не являются тремя " +"лучшими. Пожалуйста учитывайте, что это поведение может быть изменено." #: of telebot.async_telebot.AsyncTeleBot.get_game_high_scores:8 msgid "" @@ -2842,7 +2937,7 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.get_game_high_scores:10 #: telebot.async_telebot.AsyncTeleBot.retrieve_data:3 #: telebot.async_telebot.AsyncTeleBot.set_game_score:5 -#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:9 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:9 msgid "User identifier" msgstr "id пользователя" @@ -2863,8 +2958,8 @@ msgid "" "Use this method to get the current list of the bot's commands. Returns " "List of BotCommand on success." msgstr "" -"Используйте этот метод, чтобы получить текущий список команд бота. Возвращает " -"список объектов BotCommand в случае успеха." +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.get_my_commands:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#getmycommands" @@ -2883,8 +2978,9 @@ msgid "" "Use this method to get the current default administrator rights of the " "bot. Returns ChatAdministratorRights on success." msgstr "" -"Используйте этот метод, чтобы получить текущие права администратора для бота по умолчанию. " -"Возвращает объект ChatAdministratorRights в случае успеха." +"Используйте этот метод, чтобы получить текущие права администратора для " +"бота по умолчанию. Возвращает объект ChatAdministratorRights в случае " +"успеха." #: of telebot.async_telebot.AsyncTeleBot.get_my_default_administrator_rights:4 msgid "" @@ -2900,9 +2996,9 @@ msgid "" " Otherwise, the default administrator rights of the bot for groups and " "supergroups will be returned." msgstr "" -"Передайте True, чтобы получить права администратора для бота по умолчанию в каналах. " -"Иначе, будут возвращены права администратора для бота по умолчанию в группах и " -"супергруппах." +"Передайте True, чтобы получить права администратора для бота по умолчанию" +" в каналах. Иначе, будут возвращены права администратора для бота по " +"умолчанию в группах и супергруппах." #: of telebot.async_telebot.AsyncTeleBot.get_my_default_administrator_rights:9 msgid "Returns ChatAdministratorRights on success." @@ -2912,6 +3008,61 @@ msgstr "Возвращает объект ChatAdministratorRights в случа msgid ":class:`telebot.types.ChatAdministratorRights`" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.get_my_description:1 +#, fuzzy +msgid "" +"Use this method to get the current bot description for the given user " +"language. Returns BotDescription on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.get_my_description:4 +#: telebot.async_telebot.AsyncTeleBot.get_my_short_description:4 +msgid "A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_description:7 +#, fuzzy +msgid ":class:`telebot.types.BotDescription`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:1 +#, fuzzy +msgid "" +"Use this method to get the current bot name for the given user language. " +"Returns BotName on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:4 +#, fuzzy +msgid "Telegram documentation: https://core.telegram.org/bots/api#getmyname" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#getme" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:6 +msgid "Optional. A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_name:9 +#, fuzzy +msgid ":class:`telebot.types.BotName`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + +#: of telebot.async_telebot.AsyncTeleBot.get_my_short_description:1 +#, fuzzy +msgid "" +"Use this method to get the current bot short description for the given " +"user language. Returns BotShortDescription on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.get_my_short_description:7 +msgid ":class:`telebot.types.BotShortDescription`" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.get_state:1 msgid "" "Gets current state of a user. Not recommended to use this method. But it " @@ -2933,8 +3084,8 @@ msgid "" "Use this method to get a sticker set. On success, a StickerSet object is " "returned." msgstr "" -"Используйте этот метод, чтобы получить стикерпак. В случае успеха, возвращается " -"объект StickerSet." +"Используйте этот метод, чтобы получить стикерпак. В случае успеха, " +"возвращается объект StickerSet." #: of telebot.async_telebot.AsyncTeleBot.get_sticker_set:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#getstickerset" @@ -2954,8 +3105,8 @@ msgid "" "Use this method to receive incoming updates using long polling (wiki). An" " Array of Update objects is returned." msgstr "" -"Используйте этот метод, чтобы получить новые апдейты с помощью long polling-а (wiki). " -"Возвращается массив объектов Update." +"Используйте этот метод, чтобы получить новые апдейты с помощью long " +"polling-а (wiki). Возвращается массив объектов Update." #: of telebot.async_telebot.AsyncTeleBot.get_updates:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#getupdates" @@ -2974,17 +3125,17 @@ msgstr "" "id первого апдейта. Должен быть на единицу больше наибольшего id среди " "ранее полученных апдейтов. По умолчанию, возвращается список апдейтов, " "начиная с самого раннего неполученного. Апдейт считается полученным как " -"только вызван метод getUpdates со смещением больше, чем id этого апдейта. " -"Отрицательное смещение может быть указано для получения последних offset апдейтов. " -"Все предыдущие апдейты будут считаться полученными." +"только вызван метод getUpdates со смещением больше, чем id этого апдейта." +" Отрицательное смещение может быть указано для получения последних offset" +" апдейтов. Все предыдущие апдейты будут считаться полученными." #: of telebot.async_telebot.AsyncTeleBot.get_updates:12 msgid "" "Limits the number of updates to be retrieved. Values between 1-100 are " "accepted. Defaults to 100." msgstr "" -"Максимальное число апдейтов для получения. Допускаются значения от 1 до 100. " -"По умолчанию 100." +"Максимальное число апдейтов для получения. Допускаются значения от 1 до " +"100. По умолчанию 100." #: of telebot.async_telebot.AsyncTeleBot.get_updates:15 #: telebot.async_telebot.AsyncTeleBot.get_webhook_info:6 @@ -2997,8 +3148,9 @@ msgid "Array of string. List the types of updates you want your bot to receive." msgstr "Массив строк. Список видов апдейтов, которые вы хотите получать." #: of telebot.async_telebot.AsyncTeleBot.get_updates:21 -msgid "Timeout in seconds for long polling." -msgstr "Тайм-аут поллинга в секундах." +#, fuzzy +msgid "Timeout in seconds for request." +msgstr "Таймаут запроса в секундах." #: of telebot.async_telebot.AsyncTeleBot.get_updates:24 msgid "An Array of Update objects is returned." @@ -3056,9 +3208,9 @@ msgid "" " success, returns a WebhookInfo object. If the bot is using getUpdates, " "will return an object with the url field empty." msgstr "" -"Используйте этот метод, чтобы получить текущий статус вебхука. Не требует параметров. " -"В случае успеха возвращает объект WebhookInfo. Если бот использует getUpdates, " -"вернёт объект с пустым атрибутом url." +"Используйте этот метод, чтобы получить текущий статус вебхука. Не требует" +" параметров. В случае успеха возвращает объект WebhookInfo. Если бот " +"использует getUpdates, вернёт объект с пустым атрибутом url." #: of telebot.async_telebot.AsyncTeleBot.get_webhook_info:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#getwebhookinfo" @@ -3073,7 +3225,6 @@ msgid ":class:`telebot.types.WebhookInfo`" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.hide_general_forum_topic:1 - msgid "" "Use this method to hide the 'General' topic in a forum supergroup chat. " "The bot must be an administrator in the chat for this to work and must " @@ -3085,7 +3236,6 @@ msgstr "" "True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.hide_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#hidegeneralforumtopic" @@ -3096,8 +3246,8 @@ msgid "" "Wrap polling with infinite loop and exception handling to avoid bot stops" " polling." msgstr "" -"Запустить поллинг в бесконечном цикле с обработкой исключений, чтобы избежать " -"непредвиденных остановок поллинга." +"Запустить поллинг в бесконечном цикле с обработкой исключений, чтобы " +"избежать непредвиденных остановок поллинга." #: of telebot.async_telebot.AsyncTeleBot.infinity_polling:4 #: telebot.async_telebot.AsyncTeleBot.polling:15 @@ -3123,8 +3273,8 @@ msgid "" "Custom logging level for infinity_polling logging. Use logger levels from" " logging as a value. None/NOTSET = no error logging" msgstr "" -"Кастомный уровень логирования для infinity_polling. Используйте уровни из " -"logging в качестве значений. None/NOTSET = не логировать ошибки." +"Кастомный уровень логирования для infinity_polling. Используйте уровни из" +" logging в качестве значений. None/NOTSET = не логировать ошибки." #: of telebot.async_telebot.AsyncTeleBot.infinity_polling:19 #: telebot.async_telebot.AsyncTeleBot.polling:32 @@ -3163,9 +3313,9 @@ msgid "" " call to the get_updates, so unwanted updates may be received for a short" " period of time." msgstr "" -"Пожалуйста учитывайте, что этот параметр не влияет на апдейты, отправленные " -"до вызова get_updates, поэтому нежелательные апдейты могут быть получены " -"в течение короткого периода времени." +"Пожалуйста учитывайте, что этот параметр не влияет на апдейты, " +"отправленные до вызова get_updates, поэтому нежелательные апдейты могут " +"быть получены в течение короткого периода времени." #: of telebot.async_telebot.AsyncTeleBot.infinity_polling:29 msgid "Restart a file on file(s) change. Defaults to False" @@ -3211,10 +3361,10 @@ msgid "" msgstr "" "Используйте этот метод, чтобы отключиться от облачного Bot API сервера " "перед локальным запуском бота. Вы ДОЛЖНЫ отключить бота перед тем, как " -"запускать его локально, иначе нет никаких гарантий, что бот будет получать " -"апдейты. После успешного вызова, вы можете тут же подключиться к локальному " -"серверу, но не сможете подключиться обратно к облачному Bot API серверу в " -"течение 10 минут. Возвращает True в случае успеха." +"запускать его локально, иначе нет никаких гарантий, что бот будет " +"получать апдейты. После успешного вызова, вы можете тут же подключиться к" +" локальному серверу, но не сможете подключиться обратно к облачному Bot " +"API серверу в течение 10 минут. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.log_out:8 msgid "Telegram documentation: https://core.telegram.org/bots/api#logout" @@ -3227,8 +3377,8 @@ msgid "" ":class:`telebot.types.Message` object. All message handlers are tested in" " the order they were added." msgstr "" -"Обрабатывает входящие сообщения всех видов - text, photo, sticker, и т.д. " -"В качестве параметра передаёт в декорируемую функцию объект " +"Обрабатывает входящие сообщения всех видов - text, photo, sticker, и т.д." +" В качестве параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.Message`. Все хендлеры сообщений проверяются в том " "порядке, в котором были добавлены." @@ -3246,9 +3396,9 @@ msgid "" "first parameter. It must return True if the command should handle the " "message." msgstr "" -"Необязательная lambda функция. Получает сообщение (объект Message) в качестве " -"первого параметра. Функция должна вернуть True если хендлер должен обработать " -"сообщение." +"Необязательная lambda функция. Получает сообщение (объект Message) в " +"качестве первого параметра. Функция должна вернуть True если хендлер " +"должен обработать сообщение." #: of telebot.async_telebot.AsyncTeleBot.message_handler:52 #: telebot.async_telebot.AsyncTeleBot.register_edited_channel_post_handler:23 @@ -3275,9 +3425,9 @@ msgid "" "administrator in the chat for this to work and must have the appropriate " "admin rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы закрепить сообщение в супергруппе. Бот должен " -"быть администратором чата и иметь соответствующие права администратора. " -"Возвращает True в случае успеха." +"Используйте этот метод, чтобы закрепить сообщение в супергруппе. Бот " +"должен быть администратором чата и иметь соответствующие права " +"администратора. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.pin_chat_message:5 msgid "Telegram documentation: https://core.telegram.org/bots/api#pinchatmessage" @@ -3292,8 +3442,8 @@ msgid "" "Pass True, if it is not necessary to send a notification to all group " "members about the new pinned message" msgstr "" -"Передайте True, если всем участникам группы необходимо отправить уведомление " -"о закреплённом сообщении" +"Передайте True, если всем участникам группы необходимо отправить " +"уведомление о закреплённом сообщении" #: of telebot.async_telebot.AsyncTeleBot.poll_answer_handler:1 msgid "" @@ -3304,8 +3454,8 @@ msgid "" msgstr "" "Обрабатывает изменения ответа пользователя в не анонимном опросе(когда " "пользователь меняет выбор). Боты получают новые ответы только в опросах, " -"которые отправили сами. В качестве параметра передаёт в декорируемую функцию " -"объект :class:`telebot.types.PollAnswer`." +"которые отправили сами. В качестве параметра передаёт в декорируемую " +"функцию объект :class:`telebot.types.PollAnswer`." #: of telebot.async_telebot.AsyncTeleBot.poll_handler:1 msgid "" @@ -3313,9 +3463,10 @@ msgid "" "polls and polls, which are sent by the bot As a parameter to the " "decorator function, it passes :class:`telebot.types.Poll` object." msgstr "" -"Обрабатывает изменения в состоянии опроса. Боты получают только апдейты " -"о завершенных опросах и опросах, которые отправили сами. В качестве " -"параметра передаёт в декорируемую функцию объект :class:`telebot.types.Poll`." +"Обрабатывает изменения в состоянии опроса. Боты получают только апдейты о" +" завершенных опросах и опросах, которые отправили сами. В качестве " +"параметра передаёт в декорируемую функцию объект " +":class:`telebot.types.Poll`." #: of telebot.async_telebot.AsyncTeleBot.polling:1 msgid "" @@ -3340,8 +3491,8 @@ msgid "" "Set non_stop=True if you want your bot to continue receiving updates if " "there is an error." msgstr "" -"Укажите non_stop=True, если хотите чтобы ваш бот продолжать получать апдейты " -"при возникновении ошибок." +"Укажите non_stop=True, если хотите чтобы ваш бот продолжать получать " +"апдейты при возникновении ошибок." #: of telebot.async_telebot.AsyncTeleBot.polling:17 msgid "Do not stop polling when an ApiException occurs." @@ -3354,8 +3505,8 @@ msgstr "Задержка между получением апдейтов" #: of telebot.async_telebot.AsyncTeleBot.polling:42 msgid "Deprecated, use non_stop. Old typo, kept for backward compatibility." msgstr "" -"Устарело, используйте non_stop. " -"Старая опечатка, оставлено для обратной совместимости" +"Устарело, используйте non_stop. Старая опечатка, оставлено для обратной " +"совместимости" #: of telebot.async_telebot.AsyncTeleBot.polling:45 msgid "Restart a file on file(s) change. Defaults to False." @@ -3367,8 +3518,8 @@ msgid "" "checkout. As a parameter to the decorator function, it passes " ":class:`telebot.types.PreCheckoutQuery` object." msgstr "" -"Новая pre-checkout query. Содержит полную информацию о заказе. " -"В качестве параметра передаёт в декорируемую функцию объект " +"Новая pre-checkout query. Содержит полную информацию о заказе. В качестве" +" параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.PreCheckoutQuery`." #: of telebot.async_telebot.AsyncTeleBot.process_new_updates:1 @@ -3376,8 +3527,8 @@ msgid "" "Process new updates. Just pass list of updates - each update should be " "instance of Update object." msgstr "" -"Обрабатывает новые апдейты. Просто передайте список апдейтов(Update и " -"его наследники)." +"Обрабатывает новые апдейты. Просто передайте список апдейтов(Update и его" +" наследники)." #: of telebot.async_telebot.AsyncTeleBot.process_new_updates:5 msgid "list of updates" @@ -3390,9 +3541,10 @@ msgid "" "have the appropriate admin rights. Pass False for all boolean parameters " "to demote a user." msgstr "" -"Используйте этот метод, чтобы повысить или понизить пользователя в супергруппе " -"или канале. Бот должен быть администратором чата и иметь соответствующие права " -"администратора. Передайте False во все boolean параметры, чтобы понизить пользователя." +"Используйте этот метод, чтобы повысить или понизить пользователя в " +"супергруппе или канале. Бот должен быть администратором чата и иметь " +"соответствующие права администратора. Передайте False во все boolean " +"параметры, чтобы понизить пользователя." #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:5 msgid "" @@ -3406,44 +3558,53 @@ msgstr "" msgid "" "Unique identifier for the target chat or username of the target channel (" " in the format @channelusername)" -msgstr "" -"Уникальный id чата или username канала (в формате @channelusername)" +msgstr "Уникальный id чата или username канала (в формате @channelusername)" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:14 msgid "" "Pass True, if the administrator can change chat title, photo and other " "settings" msgstr "" -"Передайте True, если администратор может менять название чата, аватарку " -"и другие настройки" +"Передайте True, если администратор может менять название чата, аватарку и" +" другие настройки" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:17 msgid "Pass True, if the administrator can create channel posts, channels only" -msgstr "Передайте True, если администратор может создавать посты в канале, только для каналов" +msgstr "" +"Передайте True, если администратор может создавать посты в канале, только" +" для каналов" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:20 msgid "" "Pass True, if the administrator can edit messages of other users, " "channels only" msgstr "" -"Передайте True, если администратор может изменять сообщения других пользователей, " -"только для каналов" +"Передайте True, если администратор может изменять сообщения других " +"пользователей, только для каналов" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:23 msgid "Pass True, if the administrator can delete messages of other users" -msgstr "Передайте True, если администратор может удалять сообщения других пользователей" +msgstr "" +"Передайте True, если администратор может удалять сообщения других " +"пользователей" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:26 msgid "Pass True, if the administrator can invite new users to the chat" -msgstr "Передайте True, если администратор может приглашать новых пользователей в чат" +msgstr "" +"Передайте True, если администратор может приглашать новых пользователей в" +" чат" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:29 msgid "Pass True, if the administrator can restrict, ban or unban chat members" -msgstr "Передайте True, если администратор может ограничивать, банить или разбанивать участников чата" +msgstr "" +"Передайте True, если администратор может ограничивать, банить или " +"разбанивать участников чата" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:32 msgid "Pass True, if the administrator can pin messages, supergroups only" -msgstr "Передайте True, если администратор может закреплять сообщения, только для супергрупп" +msgstr "" +"Передайте True, если администратор может закреплять сообщения, только для" +" супергрупп" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:35 msgid "" @@ -3452,9 +3613,10 @@ msgid "" "directly or indirectly (promoted by administrators that were appointed by" " him)" msgstr "" -"Передайте True, если администратор может добавлять новых администраторов с " -"подмножеством его собственных прав администратора или понижать администраторов, " -"которых он повысил, напрямую или косвенно (администраторами, которых он назначил)" +"Передайте True, если администратор может добавлять новых администраторов " +"с подмножеством его собственных прав администратора или понижать " +"администраторов, которых он повысил, напрямую или косвенно " +"(администраторами, которых он назначил)" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:40 msgid "Pass True, if the administrator's presence in the chat is hidden" @@ -3467,19 +3629,19 @@ msgid "" "anonymous administrators in supergroups and ignore slow mode. Implied by " "any other administrator privilege" msgstr "" -"Передайте True, если администратор имеет доступ к логу событий чата, статистике " -"чата, статистике сообщений в каналах, видеть участников канала, видеть анонимных " -"администраторов в супергруппах и игнорировать медленный режим. Подразумевается " -"любым другим правом администратора" +"Передайте True, если администратор имеет доступ к логу событий чата, " +"статистике чата, статистике сообщений в каналах, видеть участников " +"канала, видеть анонимных администраторов в супергруппах и игнорировать " +"медленный режим. Подразумевается любым другим правом администратора" #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:49 msgid "" "Pass True, if the administrator can manage voice chats For now, bots can " "use this privilege only for passing to other administrators." msgstr "" -"Передайте True, если администратор может управлять голосовыми чатами. На текущий " -"момент, боты могут использовать это право администратора только для передачи другим " -"администраторам." +"Передайте True, если администратор может управлять голосовыми чатами. На " +"текущий момент, боты могут использовать это право администратора только " +"для передачи другим администраторам." #: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:53 msgid "Deprecated, use can_manage_video_chats." @@ -3490,8 +3652,8 @@ msgid "" "Pass True if the user is allowed to create, rename, close, and reopen " "forum topics, supergroups only" msgstr "" -"Передайте True, если пользователю разрешено создавать, переименовывать, закрывать, " -"и возобновлять топики, только для супергрупп" +"Передайте True, если пользователю разрешено создавать, переименовывать, " +"закрывать, и возобновлять топики, только для супергрупп" #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:1 msgid "Registers callback query handler." @@ -3532,8 +3694,8 @@ msgid "" "True if you need to pass TeleBot instance to handler(useful for " "separating handlers into different files)" msgstr "" -"True, если вам нужно передать экземпляр класса TeleBot в хендлер(удобно для " -"разбиения кода на файлы)" +"True, если вам нужно передать экземпляр класса TeleBot в хендлер(удобно " +"для разбиения кода на файлы)" #: of telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:1 msgid "Registers channel post message handler." @@ -3623,35 +3785,33 @@ msgid "" "the can_manage_topics administrator rights, unless it is the creator of " "the topic. Returns True on success." msgstr "" -"Используйте этот метод, чтобы возобновить закрытый топик в супергруппе с топиками. " -"Бот должен быть администратором чата и иметь права администратора can_manage_topics, " -"кроме случаев, когда бот является создателем топика. Возвращает True в случае успеха." +"Используйте этот метод, чтобы возобновить закрытый топик в супергруппе с " +"топиками. Бот должен быть администратором чата и иметь права " +"администратора can_manage_topics, кроме случаев, когда бот является " +"создателем топика. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:5 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#reopenforumtopic" -msgstr "" -"Документация Telegram: " -"https://core.telegram.org/bots/api#reopenforumtopic" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#reopenforumtopic" #: of telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:10 msgid "Identifier of the topic to reopen" msgstr "id топика для возобновления" #: of telebot.async_telebot.AsyncTeleBot.reopen_general_forum_topic:1 - msgid "" "Use this method to reopen the 'General' topic in a forum supergroup chat." " The bot must be an administrator in the chat for this to work and must " "have can_manage_topics administrator rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы возобновить топик 'General' в супергруппе с топиками. " -"Бот должен быть администратором чата и иметь права администратора can_manage_topics, " -"кроме случаев, когда бот является создателем топика. Возвращает True в случае успеха." +"Используйте этот метод, чтобы возобновить топик 'General' в супергруппе с" +" топиками. Бот должен быть администратором чата и иметь права " +"администратора can_manage_topics, кроме случаев, когда бот является " +"создателем топика. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.reopen_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#reopengeneralforumtopic" @@ -3707,18 +3867,24 @@ msgstr "" "Документация Telegram: " "https://core.telegram.org/bots/api#restrictchatmember" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:14 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:8 +msgid "" +"Individual parameters are deprecated and will be removed, use " +"'permissions' instead" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:17 msgid "" "Date when restrictions will be lifted for the user, unix time. If user is" " restricted for more than 366 days or less than 30 seconds from the " "current time, they are considered to be restricted forever" msgstr "" "Дата, когда ограничения будут сняты с пользователя, UNIX timestamp. Если " -"пользователь ограничен более чем на 366 дней или менее чем на 30 секунд с " -"текущего момента, он будет ограничен навсегда (пока ограничения не будут " -"сняты вручную)" +"пользователь ограничен более чем на 366 дней или менее чем на 30 секунд с" +" текущего момента, он будет ограничен навсегда (пока ограничения не будут" +" сняты вручную)" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:19 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:22 msgid "" "Pass True, if the user can send text messages, contacts, locations and " "venues" @@ -3726,62 +3892,79 @@ msgstr "" "Передайте True, если пользователь может отправлять текстовые сообщения, " "контакты, местоположения и места" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:22 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:25 msgid "" "Pass True, if the user can send audios, documents, photos, videos, video " "notes and voice notes, implies can_send_messages" msgstr "" -"Передайте True, если пользователь может отправлять аудио, документы, фото, " -"видео, видео заметки (кружочки) и аудио заметки (голосовые), подразумевает " -"can_send_messages" +"Передайте True, если пользователь может отправлять аудио, документы, " +"фото, видео, видео заметки (кружочки) и аудио заметки (голосовые), " +"подразумевает can_send_messages" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:26 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:29 msgid "Pass True, if the user is allowed to send polls, implies can_send_messages" msgstr "" -"Передайте True, если пользователю разрешено отправлять опросы, подразумевает " -"can_send_messages" +"Передайте True, если пользователю разрешено отправлять опросы, " +"подразумевает can_send_messages" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:29 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:32 msgid "" "Pass True, if the user can send animations, games, stickers and use " "inline bots, implies can_send_media_messages" msgstr "" -"Передайте True, если пользователь может отправлять гифки, игры, стикеры и " -"использовать inline ботов, подразумевает can_send_media_messages" +"Передайте True, если пользователь может отправлять гифки, игры, стикеры и" +" использовать inline ботов, подразумевает can_send_media_messages" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:32 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:35 msgid "" "Pass True, if the user may add web page previews to their messages, " "implies can_send_media_messages" msgstr "" -"Передайте True, если пользователь может добавлять превью ссылок к своим сообщениям, " -"подразумевает can_send_media_messages" +"Передайте True, если пользователь может добавлять превью ссылок к своим " +"сообщениям, подразумевает can_send_media_messages" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:36 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:39 msgid "" "Pass True, if the user is allowed to change the chat title, photo and " "other settings. Ignored in public supergroups" msgstr "" -"Передайте True, если пользователю разрешено изменять название чата, аватарку и " -"другие настройки. Игнорируется в публичных супергруппах" +"Передайте True, если пользователю разрешено изменять название чата, " +"аватарку и другие настройки. Игнорируется в публичных супергруппах" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:40 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:43 msgid "" "Pass True, if the user is allowed to invite new users to the chat, " "implies can_invite_users" -msgstr "" -"Передайте True, если пользователю разрешено приглашать пользователей в чат" +msgstr "Передайте True, если пользователю разрешено приглашать пользователей в чат" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:44 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:47 msgid "" "Pass True, if the user is allowed to pin messages. Ignored in public " "supergroups" msgstr "" -"Передайте True, если пользователю разрешено закреплять сообщения. Игнорируется " -"в публичных супергруппах" +"Передайте True, если пользователю разрешено закреплять сообщения. " +"Игнорируется в публичных супергруппах" -#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:47 +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:50 #: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:14 +msgid "" +"Pass True if chat permissions are set independently. Otherwise, the " +"can_send_other_messages and can_add_web_page_previews permissions will " +"imply the can_send_messages, can_send_audios, can_send_documents, " +"can_send_photos, can_send_videos, can_send_video_notes, and " +"can_send_voice_notes permissions; the can_send_polls permission will " +"imply the can_send_messages permission." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:56 +msgid "" +"Pass ChatPermissions object to set all permissions at once. Use this " +"parameter instead of passing all boolean parameters to avoid backward " +"compatibility problems in future." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.restrict_chat_member:60 +#: telebot.async_telebot.AsyncTeleBot.set_chat_permissions:20 #: telebot.async_telebot.AsyncTeleBot.unban_chat_member:19 msgid "True on success" msgstr "True в случае успеха" @@ -3805,10 +3988,10 @@ msgid "" "must be an administrator in the chat for this to work and must have the " "appropriate admin rights." msgstr "" -"Используйте этот метод, чтобы аннулировать ссылку-приглашение, созданную ботом. " -"Примечание: Если аннулируется главная ссылка-приглашение, автоматически " -"генерируется новая. Бот должен быть администратором чата и иметь соответствующие " -"права администратора." +"Используйте этот метод, чтобы аннулировать ссылку-приглашение, созданную " +"ботом. Примечание: Если аннулируется главная ссылка-приглашение, " +"автоматически генерируется новая. Бот должен быть администратором чата и " +"иметь соответствующие права администратора." #: of telebot.async_telebot.AsyncTeleBot.revoke_chat_invite_link:5 msgid "" @@ -3830,39 +4013,39 @@ msgstr "Этот класс устанавливает вебхуки и мон msgid "IP address to listen to. Defaults to 0.0.0.0" msgstr "IP адрес для мониторинга. По умолчанию 0.0.0.0" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:5 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:4 msgid "A port which will be used to listen to webhooks." msgstr "Порт, который будет использован для мониторинга вебхуков." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:6 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:5 msgid "Path to the webhook. Defaults to /token" msgstr "Путь к вебхуку. По умолчанию /token." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:7 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:6 msgid "Path to the certificate file." msgstr "Путь к файлу с SSL сертификатом." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:8 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:7 msgid "Path to the certificate key file." msgstr "Путь к файлу с приватным ключом SSL сертификата." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:9 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:8 msgid "Webhook URL." msgstr "URL вебхука." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:10 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:9 msgid "" "Maximum allowed number of simultaneous HTTPS connections to the webhook " "for update delivery, 1-100. Defaults to 40. Use lower values to limit the" " load on your bot's server, and higher values to increase your bot's " "throughput." msgstr "" -"Максимально-допустимое количество одновременных HTTPS подключений к вебхуку " -"для доставки апдейтов, 1-100. По умолчанию 40. Используйте меньшие значения, " -" чтобы уменьшить нагрузку на ваш сервер и большие значения для увеличения " -"пропускной способности вашего бота." +"Максимально-допустимое количество одновременных HTTPS подключений к " +"вебхуку для доставки апдейтов, 1-100. По умолчанию 40. Используйте " +"меньшие значения, чтобы уменьшить нагрузку на ваш сервер и большие " +"значения для увеличения пропускной способности вашего бота." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:11 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:10 msgid "" "A JSON-serialized list of the update types you want your bot to receive. " "For example, specify [“message”, “edited_channel_post”, “callback_query”]" @@ -3875,29 +4058,39 @@ msgstr "" "Например, укажите [“message”, “edited_channel_post”, “callback_query”], " "чтобы получать апдейты только этих видов. Полный список доступных видов " "апдейтов - util.update_types. Укажите пустой список, чтобы получать все " -"апдейты, кроме chat_member (по умолчанию). Если не задан, будет использована " -"последняя настройка." +"апдейты, кроме chat_member (по умолчанию). Если не задан, будет " +"использована последняя настройка." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:12 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:11 msgid "" "The fixed IP address which will be used to send webhook requests instead " "of the IP address resolved through DNS" msgstr "" -"Фиксированный IP адрес, который будет использоваться для отправки запросов " -"к вебхуку вместо IP адреса, полученного через DNS" +"Фиксированный IP адрес, который будет использоваться для отправки " +"запросов к вебхуку вместо IP адреса, полученного через DNS" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:13 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:12 msgid "Pass True to drop all pending updates" msgstr "Передайте True, чтобы проигнорировать все апдейты, полученные до запуска" -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:14 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:13 msgid "Integer. Request connection timeout" msgstr "Integer. Тайм-аут запроса на подключение." -#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:15 +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:14 msgid "Secret token to be used to verify the webhook request." msgstr "Секретный токен для верификации запроса к вебхуку." +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:15 +#, fuzzy +msgid "Length of a secret token, defaults to 20" +msgstr "Тайм-аут запроса, по умолчанию None" + +#: of telebot.async_telebot.AsyncTeleBot.run_webhooks:16 +#, fuzzy +msgid "Debug mode, defaults to False" +msgstr "Глобальный parse_mode, по умолчанию None" + #: of telebot.async_telebot.AsyncTeleBot.send_animation:1 msgid "" "Use this method to send animation files (GIF or H.264/MPEG-4 AVC video " @@ -3905,10 +4098,10 @@ msgid "" "currently send animation files of up to 50 MB in size, this limit may be " "changed in the future." msgstr "" -"Используйте этот метод, чтобы отправить гифку (GIF или H.264/MPEG-4 AVC видео " -"без звука). В случае успеха, возвращается отправленное сообщение (Message). На " -"текущий момент, боты могут отправлять гифки весом до 50 MB, это ограничение " -"может измениться в будущем." +"Используйте этот метод, чтобы отправить гифку (GIF или H.264/MPEG-4 AVC " +"видео без звука). В случае успеха, возвращается отправленное сообщение " +"(Message). На текущий момент, боты могут отправлять гифки весом до 50 MB," +" это ограничение может измениться в будущем." #: of telebot.async_telebot.AsyncTeleBot.send_animation:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendanimation" @@ -3922,9 +4115,9 @@ msgid "" "new animation using multipart/form-data." msgstr "" "Гиф-ка для отправки. Передайте file_id (String), чтобы отправить гифку, " -"которая уже загружена на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить гифку из интернета или загрузите новую гифку " -"с помощью multipart/form-data." +"которая уже загружена на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить гифку из интернета или загрузите новую " +"гифку с помощью multipart/form-data." #: of telebot.async_telebot.AsyncTeleBot.send_animation:13 msgid "Duration of sent animation in seconds" @@ -3953,18 +4146,19 @@ msgstr "" "Обложка отправленного файла; может быть проигнорирована, если генерация " "обложки поддерживается на стороне сервера. Обложка должна быть картинкой " "в формате JPEG и весить менее 200 kB. Ширина и высота обложки не должны " -"превышать 320. Игнорируется, если файл не загружен с помощью multipart/form-" -"data. Обложки не могут быть использованы повторно и могут быть загружены " -"только как новый файл, так что вы можете передать “attach://” " -"если обложка была загружена с помощью multipart/form-data под именем ." +"превышать 320. Игнорируется, если файл не загружен с помощью multipart" +"/form-data. Обложки не могут быть использованы повторно и могут быть " +"загружены только как новый файл, так что вы можете передать " +"“attach://” если обложка была загружена с помощью " +"multipart/form-data под именем ." #: of telebot.async_telebot.AsyncTeleBot.send_animation:28 msgid "" "Animation caption (may also be used when resending animation by file_id)," " 0-1024 characters after entities parsing" msgstr "" -"Подпись к гифке (может быть использована при повторной отправке гифки по file_id), " -"0-1024 символа после форматирования" +"Подпись к гифке (может быть использована при повторной отправке гифки по " +"file_id), 0-1024 символа после форматирования" #: of telebot.async_telebot.AsyncTeleBot.send_animation:31 msgid "Mode for parsing entities in the animation caption" @@ -3985,10 +4179,17 @@ msgid "Identifier of a message thread, in which the video will be sent" msgstr "id топика, в который будет отправлено видео" #: of telebot.async_telebot.AsyncTeleBot.send_animation:60 - msgid "Pass True, if the animation should be sent as a spoiler" msgstr "Передайте True, если гифку нужно отправить как спойлер" +#: of telebot.async_telebot.AsyncTeleBot.send_animation:63 +#: telebot.async_telebot.AsyncTeleBot.send_audio:63 +#: telebot.async_telebot.AsyncTeleBot.send_document:56 +#: telebot.async_telebot.AsyncTeleBot.send_video:64 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:48 +msgid "Deprecated. Use thumbnail instead" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_audio:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -3997,11 +4198,12 @@ msgid "" " audio files of up to 50 MB in size, this limit may be changed in the " "future." msgstr "" -"Используйте этот метод, чтобы отправить аудио, если вы хотите, чтобы клиенты " -"(приложения) Telegram проигрывали их в музыкальном проигрывателе. Ваше аудио " -"должно быть в формате .MP3 или .M4A. В случае успеха, возвращается отправленное " -"сообщение (Message). На текущий момент, боты могут отправлять аудио весом до 50 MB, " -"это ограничение может измениться в будущем." +"Используйте этот метод, чтобы отправить аудио, если вы хотите, чтобы " +"клиенты (приложения) Telegram проигрывали их в музыкальном проигрывателе." +" Ваше аудио должно быть в формате .MP3 или .M4A. В случае успеха, " +"возвращается отправленное сообщение (Message). На текущий момент, боты " +"могут отправлять аудио весом до 50 MB, это ограничение может измениться в" +" будущем." #: of telebot.async_telebot.AsyncTeleBot.send_audio:5 msgid "For sending voice messages, use the send_voice method instead." @@ -4020,9 +4222,9 @@ msgid "" "format." msgstr "" "Аудио для отправки. Передайте file_id (String), чтобы отправить аудио, " -"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить аудио из интернета или загрузите новое с помощью " -"multipart/form-data. Аудио должно быть в формате .MP3 или .M4A." +"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить аудио из интернета или загрузите новое с " +"помощью multipart/form-data. Аудио должно быть в формате .MP3 или .M4A." #: of telebot.async_telebot.AsyncTeleBot.send_audio:17 msgid "Audio caption, 0-1024 characters after entities parsing" @@ -4045,8 +4247,8 @@ msgid "" "Mode for parsing entities in the audio caption. See formatting options " "for more details." msgstr "" -"Режим форматирования подписи к аудио. См. formatting options " -"для получения подробностей." +"Режим форматирования подписи к аудио. См. formatting options для " +"получения подробностей." #: of telebot.async_telebot.AsyncTeleBot.send_audio:45 msgid "" @@ -4061,10 +4263,11 @@ msgstr "" "Обложка отправленного файла; может быть проигнорирована, если генерация " "обложки поддерживается на стороне сервера. Обложка должна быть картинкой " "в формате JPEG и весить менее 200 kB. Ширина и высота обложки не должны " -"превышать 320. Игнорируется, если файл не загружен с помощью multipart/form-" -"data. Обложки не могут быть использованы повторно и могут быть загружены " -"только как новый файл, так что вы можете передать “attach://” " -"если обложка была загружена с помощью multipart/form-data под именем ." +"превышать 320. Игнорируется, если файл не загружен с помощью multipart" +"/form-data. Обложки не могут быть использованы повторно и могут быть " +"загружены только как новый файл, так что вы можете передать " +"“attach://” если обложка была загружена с помощью " +"multipart/form-data под именем ." #: of telebot.async_telebot.AsyncTeleBot.send_audio:51 #: telebot.async_telebot.AsyncTeleBot.send_document:35 @@ -4074,8 +4277,8 @@ msgid "" "A JSON-serialized list of special entities that appear in the caption, " "which can be specified instead of parse_mode" msgstr "" -"Список отформатированных частей подписи в формате JSON, можно использовать вместо " -"parse_mode" +"Список отформатированных частей подписи в формате JSON, можно " +"использовать вместо parse_mode" #: of telebot.async_telebot.AsyncTeleBot.send_chat_action:1 msgid "" @@ -4086,8 +4289,8 @@ msgid "" msgstr "" "Используйте этот метод, когда вам нужно показать пользователю, что бот " "что-то делает. Статус устанавливается на 5 секунд или менее (когда от " -"бота приходит сообщение, клиенты (приложения) Telegram убирают статус typing). " -"Возвращает True в случае успеха." +"бота приходит сообщение, клиенты (приложения) Telegram убирают статус " +"typing). Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.send_chat_action:5 msgid "" @@ -4098,8 +4301,9 @@ msgid "" msgstr "" "Пример: ImageBot-у требуется время, чтобы обработать запрос и загрузить " "изображение. Вместо отправки текстового сообщения “Отправка изображения, " -"пожалуйста подождите…”, бот может использовать sendChatAction с параметром " -"action = upload_photo. Пользователь увидит статус бота “sending photo”." +"пожалуйста подождите…”, бот может использовать sendChatAction с " +"параметром action = upload_photo. Пользователь увидит статус бота " +"“sending photo”." #: of telebot.async_telebot.AsyncTeleBot.send_chat_action:8 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendchataction" @@ -4124,13 +4328,12 @@ msgid "" msgstr "" "Тип действия. Выберите один, в зависимости от того, что получит " "пользователь: typing для текстовых сообщений, upload_photo для фото, " -"record_video или upload_video для видео, record_voice или upload_voice для " -"голосовых сообщений, upload_document для файлов, choose_sticker для " -"стикеров, find_location для данных о местоположении, record_video_note или " -"upload_video_note для видео заметок (кружочков)." +"record_video или upload_video для видео, record_voice или upload_voice " +"для голосовых сообщений, upload_document для файлов, choose_sticker для " +"стикеров, find_location для данных о местоположении, record_video_note " +"или upload_video_note для видео заметок (кружочков)." #: of telebot.async_telebot.AsyncTeleBot.send_chat_action:22 - msgid "The thread to which the message will be sent(supergroups only)" msgstr "id топика, в который сообщение будет отправлено(только для супергрупп)" @@ -4139,8 +4342,8 @@ msgid "" "Use this method to send phone contacts. On success, the sent Message is " "returned." msgstr "" -"Используйте этот метод, чтобы отправить контакт. В случае успеха, возвращается " -"отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить контакт. В случае успеха, " +"возвращается отправленное сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_contact:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendcontact" @@ -4169,8 +4372,8 @@ msgid "" "Pass True, if the message should be sent even if one of the specified " "replied-to messages is not found." msgstr "" -"Передайте True, если сообщение должно быть отправлено даже если одно из сообщений, " -"на которые нужно ответить, не найдено." +"Передайте True, если сообщение должно быть отправлено даже если одно из " +"сообщений, на которые нужно ответить, не найдено." #: of telebot.async_telebot.AsyncTeleBot.send_contact:41 #: telebot.async_telebot.AsyncTeleBot.send_venue:54 @@ -4182,8 +4385,9 @@ msgid "" "Use this method to send an animated emoji that will display a random " "value. On success, the sent Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить анимированный эмодзи, который покажет " -"случайное значение. В случае успеха, возвращается отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить анимированный эмодзи, который " +"покажет случайное значение. В случае успеха, возвращается отправленное " +"сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_dice:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#senddice" @@ -4196,9 +4400,9 @@ msgid "" " and “🎳”, values 1-5 for “🏀” and “⚽”, and values 1-64 for “🎰”. Defaults " "to “🎲”" msgstr "" -"Эмодзи, на котором основана анимация. На текущий момент, должно быть одним из " -"“🎲”, “🎯”, “🏀”, “⚽”, “🎳”, или “🎰”. Значение может быть 1-6 для “🎲”, “🎯”" -" и “🎳”, 1-5 для “🏀” и “⚽”, и 1-64 для “🎰”. По умолчанию “🎲”" +"Эмодзи, на котором основана анимация. На текущий момент, должно быть " +"одним из “🎲”, “🎯”, “🏀”, “⚽”, “🎳”, или “🎰”. Значение может быть 1-6 для " +"“🎲”, “🎯” и “🎳”, 1-5 для “🏀” и “⚽”, и 1-64 для “🎰”. По умолчанию “🎲”" #: of telebot.async_telebot.AsyncTeleBot.send_dice:29 msgid "Protects the contents of the sent message from forwarding" @@ -4225,18 +4429,18 @@ msgid "" "String for Telegram to get a file from the Internet, or upload a new one " "using multipart/form-data" msgstr "" -"(документ) Файл для отправки. Передайте file_id (String), чтобы отправить файл, " -"который уже загружен на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить файл из интернета или загрузите новый с помощью " -"multipart/form-data" +"(документ) Файл для отправки. Передайте file_id (String), чтобы отправить" +" файл, который уже загружен на сервера Telegram (рекомендуется), " +"передайте HTTP URL (String), чтобы отправить файл из интернета или " +"загрузите новый с помощью multipart/form-data" #: of telebot.async_telebot.AsyncTeleBot.send_document:15 msgid "" "Document caption (may also be used when resending documents by file_id), " "0-1024 characters after entities parsing" msgstr "" -"Подпись к файлу (может быть использована при повторной отправке файла по file_id), " -"0-1024 символа после форматирования" +"Подпись к файлу (может быть использована при повторной отправке файла по " +"file_id), 0-1024 символа после форматирования" #: of telebot.async_telebot.AsyncTeleBot.send_document:23 msgid "Mode for parsing entities in the document caption" @@ -4253,29 +4457,30 @@ msgid "" "“attach://” if the thumbnail was uploaded using " "multipart/form-data under " msgstr "" -"InputFile или String : Обложка отправленного файла; может быть проигнорирована, " -"если генерация обложки поддерживается на стороне сервера. Обложка должна " -"быть картинкой в формате JPEG и весить менее 200 kB. Ширина и высота обложки " -"не должны превышать 320. Игнорируется, если файл не загружен с помощью " -"multipart/form-data. Обложки не могут быть использованы повторно и могут быть " -"загружены только как новый файл, так что вы можете передать " -"“attach://” если обложка была загружена с помощью " -"multipart/form-data под именем ." +"InputFile или String : Обложка отправленного файла; может быть " +"проигнорирована, если генерация обложки поддерживается на стороне " +"сервера. Обложка должна быть картинкой в формате JPEG и весить менее 200 " +"kB. Ширина и высота обложки не должны превышать 320. Игнорируется, если " +"файл не загружен с помощью multipart/form-data. Обложки не могут быть " +"использованы повторно и могут быть загружены только как новый файл, так " +"что вы можете передать “attach://” если обложка была " +"загружена с помощью multipart/form-data под именем ." #: of telebot.async_telebot.AsyncTeleBot.send_document:41 msgid "" "allows to define file name that will be visible in the Telegram instead " "of original file name" msgstr "" -"позволяет задать имя файла, которое будет показано в Telegram вместо настоящего" +"позволяет задать имя файла, которое будет показано в Telegram вместо " +"настоящего" #: of telebot.async_telebot.AsyncTeleBot.send_document:44 msgid "" "Disables automatic server-side content type detection for files uploaded " "using multipart/form-data" msgstr "" -"Отключает автоматическое обнаружение типа файла на стороне сервера для файлов, " -"загруженных с помощью multipart/form-data" +"Отключает автоматическое обнаружение типа файла на стороне сервера для " +"файлов, загруженных с помощью multipart/form-data" #: of telebot.async_telebot.AsyncTeleBot.send_document:47 #: telebot.async_telebot.AsyncTeleBot.send_sticker:33 @@ -4296,8 +4501,8 @@ msgid "" "Short name of the game, serves as the unique identifier for the game. Set" " up your games via @BotFather." msgstr "" -"Короткое имя игры, служит в качестве уникального id игры. Настройте свои игры" -"через @BotFather." +"Короткое имя игры, служит в качестве уникального id игры. Настройте свои " +"игрычерез @BotFather." #: of telebot.async_telebot.AsyncTeleBot.send_game:20 msgid "Timeout in seconds for waiting for a response from the bot." @@ -4308,7 +4513,8 @@ msgid "" "Pass True, if content of the message needs to be protected from being " "viewed by the bot." msgstr "" -"Передайте True, если содержимое сообщение должно быть защищено от просмотра ботом." +"Передайте True, если содержимое сообщение должно быть защищено от " +"просмотра ботом." #: of telebot.async_telebot.AsyncTeleBot.send_game:29 msgid "Identifier of the thread to which the message will be sent." @@ -4346,8 +4552,8 @@ msgid "" "a marketing image for a service. People like it better when they see what" " they are paying for." msgstr "" -"URL фото продукта. Может быть фото товаров или рекламным изображением сервиса. " -"Людям больше нравится, когда они видят, за что платят." +"URL фото продукта. Может быть фото товаров или рекламным изображением " +"сервиса. Людям больше нравится, когда они видят, за что платят." #: of telebot.async_telebot.AsyncTeleBot.send_invoice:73 msgid "" @@ -4355,9 +4561,9 @@ msgid "" " price' button will be shown. If not empty, the first button must be a " "Pay button" msgstr "" -"JSON-сериализованный объект inline клавиатуры. Если пустой, будет показана " -"одна кнопка 'Pay total price'. Если не пустой, первая кнопка должна быть " -"кнопкой для оплаты" +"JSON-сериализованный объект inline клавиатуры. Если пустой, будет " +"показана одна кнопка 'Pay total price'. Если не пустой, первая кнопка " +"должна быть кнопкой для оплаты" #: of telebot.async_telebot.AsyncTeleBot.send_invoice:81 #: telebot.async_telebot.AsyncTeleBot.set_webhook:39 @@ -4403,8 +4609,8 @@ msgid "" "For live locations, a direction in which the user is moving, in degrees. " "Must be between 1 and 360 if specified." msgstr "" -"Для live местоположений, направление, в котором пользователь двигается, в градусах. " -"Должно быть между 1 и 360, если указано." +"Для live местоположений, направление, в котором пользователь двигается, в" +" градусах. Должно быть между 1 и 360, если указано." #: of telebot.async_telebot.AsyncTeleBot.send_location:37 msgid "" @@ -4413,8 +4619,8 @@ msgid "" "if specified." msgstr "" "Для live местоположений, максимальное расстояние для уведомлений о " -"приближении другого участника чата, в метрах. Должно быть между 1 и 100000, " -"если указано." +"приближении другого участника чата, в метрах. Должно быть между 1 и " +"100000, если указано." #: of telebot.async_telebot.AsyncTeleBot.send_media_group:1 msgid "" @@ -4423,9 +4629,10 @@ msgid "" " messages of the same type. On success, an array of Messages that were " "sent is returned." msgstr "" -"Используйте этот метод, чтобы отправить группу фото, видео, файлов или аудио " -"как альбом. Файлы и аудио могут быть сгруппированы в альбом только с сообщениями " -"того же типа. В случае успеха, возвращается массив отправленных сообщений (Message)." +"Используйте этот метод, чтобы отправить группу фото, видео, файлов или " +"аудио как альбом. Файлы и аудио могут быть сгруппированы в альбом только " +"с сообщениями того же типа. В случае успеха, возвращается массив " +"отправленных сообщений (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_media_group:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendmediagroup" @@ -4436,16 +4643,16 @@ msgid "" "A JSON-serialized array describing messages to be sent, must include 2-10" " items" msgstr "" -"JSON-сериализованный массив, описывающий сообщения для отправки, должен включать " -"от 2 до 10 элементов" +"JSON-сериализованный массив, описывающий сообщения для отправки, должен " +"включать от 2 до 10 элементов" #: of telebot.async_telebot.AsyncTeleBot.send_media_group:12 msgid "" "Sends the messages silently. Users will receive a notification with no " "sound." msgstr "" -"Отправить сообщение, при получении которого пользователя пользователи получат " -"уведомление без звука." +"Отправить сообщение, при получении которого пользователя пользователи " +"получат уведомление без звука." #: of telebot.async_telebot.AsyncTeleBot.send_media_group:27 msgid "Identifier of a message thread, in which the messages will be sent" @@ -4466,8 +4673,9 @@ msgid "" "characters, use the `split_string` or `smart_split` function in util.py." msgstr "" "Предупреждение: Не отправляйте больше 4096 символов в одном сообщении, " -"иначе вы рискуете получить ошибку HTTP 414. Если вам нужно отправить больше " -"4096 символов, используйте функцию `split_string` или `smart_split` из util.py." +"иначе вы рискуете получить ошибку HTTP 414. Если вам нужно отправить " +"больше 4096 символов, используйте функцию `split_string` или " +"`smart_split` из util.py." #: of telebot.async_telebot.AsyncTeleBot.send_message:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendmessage" @@ -4482,22 +4690,22 @@ msgid "" "List of special entities that appear in message text, which can be " "specified instead of parse_mode" msgstr "" -"Список отформатированных частей в тексте сообщения, " -"можно использовать вместо parse_mode" +"Список отформатированных частей в тексте сообщения, можно использовать " +"вместо parse_mode" #: of telebot.async_telebot.AsyncTeleBot.send_message:27 msgid "" "If True, the message content will be hidden for all users except for the " "target user" msgstr "" -"Если True, содержимое сообщения будет скрыто от всех пользователей, кроме " -"заданного" +"Если True, содержимое сообщения будет скрыто от всех пользователей, кроме" +" заданного" #: of telebot.async_telebot.AsyncTeleBot.send_photo:1 msgid "Use this method to send photos. On success, the sent Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить фото. В случае успеха, возвращается " -"отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить фото. В случае успеха, " +"возвращается отправленное сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_photo:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendphoto" @@ -4513,25 +4721,25 @@ msgid "" "must be at most 20." msgstr "" "Фото для отправки. Передайте file_id (String), чтобы отправить фото, " -"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить фото из интернета или загрузите новое с помощью " -"multipart/form-data. Фото должно весить не более 10 MB. Ширина и высота фото не " -"должны суммарно превышать 10000. Отношение ширины и высоты должно быть не более 20." +"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить фото из интернета или загрузите новое с " +"помощью multipart/form-data. Фото должно весить не более 10 MB. Ширина и " +"высота фото не должны суммарно превышать 10000. Отношение ширины и высоты" +" должно быть не более 20." #: of telebot.async_telebot.AsyncTeleBot.send_photo:13 msgid "" "Photo caption (may also be used when resending photos by file_id), 0-1024" " characters after entities parsing" msgstr "" -"Подпись к фото (может быть использована при повторной отправке файла по file_id), " -"0-1024 символа после форматирования" +"Подпись к фото (может быть использована при повторной отправке файла по " +"file_id), 0-1024 символа после форматирования" #: of telebot.async_telebot.AsyncTeleBot.send_photo:16 msgid "Mode for parsing entities in the photo caption." msgstr "Режим форматирования подписи к фото." #: of telebot.async_telebot.AsyncTeleBot.send_photo:45 - msgid "Pass True, if the photo should be sent as a spoiler" msgstr "Передайте True, если фото должно быть отправлено как спойлер" @@ -4540,8 +4748,8 @@ msgid "" "Use this method to send a native poll. On success, the sent Message is " "returned." msgstr "" -"Используйте этот метод, чтобы отправить опрос. В случае успеха, возвращается " -"отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить опрос. В случае успеха, " +"возвращается отправленное сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_poll:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendpoll" @@ -4570,16 +4778,16 @@ msgid "" "True, if the poll allows multiple answers, ignored for polls in quiz " "mode, defaults to False" msgstr "" -"True, если опрос позволяет выбрать несколько вариантов ответа, игнорируется в " -"опросах вида “quiz”, по умолчанию False" +"True, если опрос позволяет выбрать несколько вариантов ответа, " +"игнорируется в опросах вида “quiz”, по умолчанию False" #: of telebot.async_telebot.AsyncTeleBot.send_poll:24 msgid "" "0-based identifier of the correct answer option. Available only for polls" " in quiz mode, defaults to None" msgstr "" -"Индекс правильного варианта ответа, начиная с 0. Доступно только для опросов " -"вида “quiz”, по умолчанию None" +"Индекс правильного варианта ответа, начиная с 0. Доступно только для " +"опросов вида “quiz”, по умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.send_poll:28 msgid "" @@ -4604,8 +4812,8 @@ msgid "" "Amount of time in seconds the poll will be active after creation, 5-600. " "Can't be used together with close_date." msgstr "" -"Время в секундах, в течение которого опрос будет активен, 5-600. " -"Нельзя использовать вместо с close_date." +"Время в секундах, в течение которого опрос будет активен, 5-600. Нельзя " +"использовать вместо с close_date." #: of telebot.async_telebot.AsyncTeleBot.send_poll:38 msgid "Point in time (Unix timestamp) when the poll will be automatically closed." @@ -4616,12 +4824,14 @@ msgid "" "Pass True, if the poll needs to be immediately closed. This can be useful" " for poll preview." msgstr "" -"Передайте True, если опрос должен быть завершен немедленно. Может быть полезно " -"для предпросмотра опроса." +"Передайте True, если опрос должен быть завершен немедленно. Может быть " +"полезно для предпросмотра опроса." #: of telebot.async_telebot.AsyncTeleBot.send_poll:50 msgid "Pass True, if the poll allows multiple options to be voted simultaneously." -msgstr "Передайте True, если опрос позволяет выбрать несколько вариантов одновременно." +msgstr "" +"Передайте True, если опрос позволяет выбрать несколько вариантов " +"одновременно." #: of telebot.async_telebot.AsyncTeleBot.send_poll:57 msgid "Timeout in seconds for waiting for a response from the user." @@ -4632,8 +4842,8 @@ msgid "" "A JSON-serialized list of special entities that appear in the " "explanation, which can be specified instead of parse_mode" msgstr "" -"JSON-сериализованный список отформатированных частей explanation, " -"можно использовать вместо parse_mode" +"JSON-сериализованный список отформатированных частей explanation, можно " +"использовать вместо parse_mode" #: of telebot.async_telebot.AsyncTeleBot.send_poll:67 msgid "The identifier of a message thread, in which the poll will be sent" @@ -4644,8 +4854,8 @@ msgid "" "Use this method to send static .WEBP, animated .TGS, or video .WEBM " "stickers. On success, the sent Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить статичный .WEBP, анимированный .TGS, " -"или видео .WEBM стикер. В случае успеха возвращает отправленное " +"Используйте этот метод, чтобы отправить статичный .WEBP, анимированный " +".TGS, или видео .WEBM стикер. В случае успеха возвращает отправленное " "сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_sticker:4 @@ -4660,21 +4870,25 @@ msgid "" " multipart/form-data." msgstr "" "Стикер для отправки. Передайте file_id (String), чтобы отправить файл, " -"который уже загружен на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить .webp файл из интернета или загрузите новый с помощью " -"multipart/form-data." +"который уже загружен на сервера Telegram (рекомендуется), передайте HTTP " +"URL (String), чтобы отправить .webp файл из интернета или загрузите новый" +" с помощью multipart/form-data." #: of telebot.async_telebot.AsyncTeleBot.send_sticker:21 msgid "to disable the notification" msgstr "отключить уведомление" +#: of telebot.async_telebot.AsyncTeleBot.send_sticker:39 +msgid "Emoji associated with the sticker; only for just uploaded stickers" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_venue:1 msgid "" "Use this method to send information about a venue. On success, the sent " "Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить информацию о месте. В случае успеха " -"возвращается отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить информацию о месте. В случае " +"успеха возвращается отправленное сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_venue:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvenue" @@ -4723,8 +4937,9 @@ msgid "" "Use this method to send video files, Telegram clients support mp4 videos " "(other formats may be sent as Document)." msgstr "" -"Используйте этот метод, чтобы отправить видео, клиенты (приложения) Telegram " -"поддерживают mp4 видео (другие форматы могут быть отправлены как Document)." +"Используйте этот метод, чтобы отправить видео, клиенты (приложения) " +"Telegram поддерживают mp4 видео (другие форматы могут быть отправлены как" +" Document)." #: of telebot.async_telebot.AsyncTeleBot.send_video:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideo" @@ -4758,8 +4973,8 @@ msgid "" "Video caption (may also be used when resending videos by file_id), 0-1024" " characters after entities parsing" msgstr "" -"Подпись к видео (может быть использована при повторной отправке файла по file_id), " -"0-1024 символа после форматирования" +"Подпись к видео (может быть использована при повторной отправке файла по " +"file_id), 0-1024 символа после форматирования" #: of telebot.async_telebot.AsyncTeleBot.send_video:26 msgid "Mode for parsing entities in the video caption" @@ -4770,7 +4985,6 @@ msgid "Pass True, if the uploaded video is suitable for streaming" msgstr "Передайте True, если загруженное видео подходит для стриминга" #: of telebot.async_telebot.AsyncTeleBot.send_video:61 - msgid "Pass True, if the video should be sent as a spoiler" msgstr "Передайте True, если видео должно быть отправлено как спойлер" @@ -4780,10 +4994,10 @@ msgid "" "to 1 minute long. Use this method to send video messages. On success, the" " sent Message is returned." msgstr "" -"Начиная с версии v.4.0, клиенты(приложения) Telegram поддерживают скругленные " -"квадратные MPEG4 видео длительностью до минуты. Используйте этот метод, чтобы " -"отправить видео заметку (кружочек). В случае успеха возвращается отправленное " -"сообщение (Message)." +"Начиная с версии v.4.0, клиенты(приложения) Telegram поддерживают " +"скругленные квадратные MPEG4 видео длительностью до минуты. Используйте " +"этот метод, чтобы отправить видео заметку (кружочек). В случае успеха " +"возвращается отправленное сообщение (Message)." #: of telebot.async_telebot.AsyncTeleBot.send_video_note:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideonote" @@ -4796,10 +5010,10 @@ msgid "" "multipart/form-data. Sending video notes by a URL is currently " "unsupported" msgstr "" -"Видео заметка для отправки. Передайте file_id (String), чтобы отправить видео " -"заметку, которая уже загружена на сервера Telegram или загрузите новую с помощью " -"multipart/form-data. На текущий момент, отправка видео заметок по URL не " -"поддерживается" +"Видео заметка для отправки. Передайте file_id (String), чтобы отправить " +"видео заметку, которая уже загружена на сервера Telegram или загрузите " +"новую с помощью multipart/form-data. На текущий момент, отправка видео " +"заметок по URL не поддерживается" #: of telebot.async_telebot.AsyncTeleBot.send_video_note:16 msgid "Video width and height, i.e. diameter of the video message" @@ -4821,9 +5035,9 @@ msgstr "" "Используйте этот метод, чтобы отправить голосовое сообщение. Ваше аудио " "должно быть в формате .OGG и закодировано с помощью OPUS (другие форматы " "можно отправить как Audio или Document). В случае успеха возвращается " -"отправленное сообщение (Message). На текущий момент, боты могут отправлять " -"голосовые сообщения весом до 50 MB, это ограничение может быть изменено в " -"будущем." +"отправленное сообщение (Message). На текущий момент, боты могут " +"отправлять голосовые сообщения весом до 50 MB, это ограничение может быть" +" изменено в будущем." #: of telebot.async_telebot.AsyncTeleBot.send_voice:5 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvoice" @@ -4837,9 +5051,9 @@ msgid "" "multipart/form-data." msgstr "" "Аудио для отправки. Передайте file_id (String), чтобы отправить аудио, " -"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить аудио из интернета или загрузите новое с помощью " -"multipart/form-data." +"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить аудио из интернета или загрузите новое с " +"помощью multipart/form-data." #: of telebot.async_telebot.AsyncTeleBot.send_voice:14 msgid "Voice message caption, 0-1024 characters after entities parsing" @@ -4854,8 +5068,8 @@ msgid "" "Mode for parsing entities in the voice message caption. See formatting " "options for more details." msgstr "" -"Режим форматирования подписи к голосовому сообщению. См. formatting options " -"для получения подробностей." +"Режим форматирования подписи к голосовому сообщению. См. formatting " +"options для получения подробностей." #: of telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:1 msgid "" @@ -4877,9 +5091,7 @@ msgstr "" msgid "" "New custom title for the administrator; 0-16 characters, emoji are not " "allowed" -msgstr "" -"Новое кастомное звание администратора; 0-16 символов, эмодзи не " -"разрешены" +msgstr "Новое кастомное звание администратора; 0-16 символов, эмодзи не разрешены" #: of telebot.async_telebot.AsyncTeleBot.set_chat_description:1 msgid "" @@ -4924,14 +5136,16 @@ msgid "" "Unique identifier for the target private chat. If not specified, default " "bot's menu button will be changed." msgstr "" -"Уникальный id приватного чата. Если не указан, будет изменена кнопка меню " -"по умолчанию." +"Уникальный id приватного чата. Если не указан, будет изменена кнопка меню" +" по умолчанию." #: of telebot.async_telebot.AsyncTeleBot.set_chat_menu_button:11 msgid "" "A JSON-serialized object for the new bot's menu button. Defaults to " "MenuButtonDefault" -msgstr "JSON-сериализованный объект новой кнопки меню. По умолчанию MenuButtonDefault" +msgstr "" +"JSON-сериализованный объект новой кнопки меню. По умолчанию " +"MenuButtonDefault" #: of telebot.async_telebot.AsyncTeleBot.set_chat_permissions:1 msgid "" @@ -4939,9 +5153,9 @@ msgid "" "must be an administrator in the group or a supergroup for this to work " "and must have the can_restrict_members admin rights." msgstr "" -"Используйте этот метод, чтобы задать права по умолчанию для всех участников чата. " -"Бот должен быть администратором группы или супергруппы и иметь права администратора " -"can_restrict_members." +"Используйте этот метод, чтобы задать права по умолчанию для всех " +"участников чата. Бот должен быть администратором группы или супергруппы и" +" иметь права администратора can_restrict_members." #: of telebot.async_telebot.AsyncTeleBot.set_chat_permissions:5 msgid "" @@ -4964,11 +5178,11 @@ msgid "" "only work if the ‘All Members Are Admins’ setting is off in the target " "group." msgstr "" -"Используйте этот метод, чтобы задать новую аватарку чата. В приватных чатах " -"аватарки менять нельзя. Бот должен быть администратором чата и иметь " -"соответствующие права администратора. Возвращает True в случае успеха. " -"Примечание: В обычных группах (не супергруппы), этот метод будет работать " -"только если настройка ‘All Members Are Admins’ отключена." +"Используйте этот метод, чтобы задать новую аватарку чата. В приватных " +"чатах аватарки менять нельзя. Бот должен быть администратором чата и " +"иметь соответствующие права администратора. Возвращает True в случае " +"успеха. Примечание: В обычных группах (не супергруппы), этот метод будет " +"работать только если настройка ‘All Members Are Admins’ отключена." #: of telebot.async_telebot.AsyncTeleBot.set_chat_photo:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#setchatphoto" @@ -4986,10 +5200,11 @@ msgid "" "optionally returned in getChat requests to check if the bot can use this " "method. Returns True on success." msgstr "" -"Используйте этот метод, чтобы задать стикерпак супергруппы. Бот должен быть " -"администратором чата и иметь соответствующие права администратора. " -"Используйте атрибут can_set_sticker_set, возвращаемые методом getChat, чтобы " -"проверить, что бот может использовать этот метод. Возвращает True в случае успеха." +"Используйте этот метод, чтобы задать стикерпак супергруппы. Бот должен " +"быть администратором чата и иметь соответствующие права администратора. " +"Используйте атрибут can_set_sticker_set, возвращаемые методом getChat, " +"чтобы проверить, что бот может использовать этот метод. Возвращает True в" +" случае успеха." #: of telebot.async_telebot.AsyncTeleBot.set_chat_sticker_set:5 msgid "" @@ -5018,8 +5233,8 @@ msgstr "" "Используйте этот метод, чтобы изменить название чата. В приватных чатах " "изменить название нельзя. Бот должен быть администратором чата и иметь " "соответствующие права админа. Возвращает True в случае успеха. " -"Примечание: В обычных группах (не супергруппы), этот метод будет работать " -"только если настройка ‘All Members Are Admins’ отключена." +"Примечание: В обычных группах (не супергруппы), этот метод будет работать" +" только если настройка ‘All Members Are Admins’ отключена." #: of telebot.async_telebot.AsyncTeleBot.set_chat_title:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#setchattitle" @@ -5029,6 +5244,24 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#se msgid "New chat title, 1-255 characters" msgstr "Новое название чата, 1-255 символов" +#: of +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:1 +#, fuzzy +msgid "" +"Use this method to set the thumbnail of a custom emoji sticker set. " +"Returns True on success." +msgstr "" +"Используйте этот метод, чтобы задать обложку стикерпака. Анимированные " +"обложки могут быть заданы только для анимированных стикерпаков. " +"Возвращает True в случае успеха." + +#: of +#: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:7 +msgid "" +"Custom emoji identifier of a sticker from the sticker set; pass an empty " +"string to drop the thumbnail and use the first sticker as the thumbnail." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_game_score:1 msgid "Sets the value of points in the game to a specific user." msgstr "Задаёт количество очков пользователя в игре." @@ -5046,8 +5279,8 @@ msgid "" "Pass True, if the high score is allowed to decrease. This can be useful " "when fixing mistakes or banning cheaters" msgstr "" -"Передайте True, если количество очков могут быть уменьшено. Может быть полезно " -"при исправлении ошибок или бане читеров" +"Передайте True, если количество очков могут быть уменьшено. Может быть " +"полезно при исправлении ошибок или бане читеров" #: of telebot.async_telebot.AsyncTeleBot.set_game_score:23 msgid "" @@ -5062,8 +5295,8 @@ msgid "" "On success, if the message was sent by the bot, returns the edited " "Message, otherwise returns True." msgstr "" -"В случае успеха, если сообщение было отправлено ботом, возвращает измененное " -"сообщение (Message), иначе возвращает True." +"В случае успеха, если сообщение было отправлено ботом, возвращает " +"измененное сообщение (Message), иначе возвращает True." #: of telebot.async_telebot.AsyncTeleBot.set_my_commands:1 msgid "Use this method to change the list of the bot's commands." @@ -5084,10 +5317,11 @@ msgid "" "rights will be suggested to users, but they are are free to modify the " "list before adding the bot. Returns True on success." msgstr "" -"Используйте этот метод, чтобы изменить права администратора по умолчанию, " -"запрашиваемые при добавлении бота в группу или канал в качестве администратора. " -"Эти права будут предложены пользователям, но пользователи могут изменить список " -"перед добавлением бота. Возвращает True в случае успеха." +"Используйте этот метод, чтобы изменить права администратора по умолчанию," +" запрашиваемые при добавлении бота в группу или канал в качестве " +"администратора. Эти права будут предложены пользователям, но пользователи" +" могут изменить список перед добавлением бота. Возвращает True в случае " +"успеха." #: of telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:7 msgid "" @@ -5102,8 +5336,9 @@ msgid "" "A JSON-serialized object describing new default administrator rights. If " "not specified, the default administrator rights will be cleared." msgstr "" -"JSON-сериалиованный объект, описывающий новые права администратора по умолчанию. " -"Если не указан, права администратора по умолчанию будут сброшены." +"JSON-сериалиованный объект, описывающий новые права администратора по " +"умолчанию. Если не указан, права администратора по умолчанию будут " +"сброшены." #: of telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:13 msgid "" @@ -5111,8 +5346,87 @@ msgid "" "channels. Otherwise, the default administrator rights of the bot for " "groups and supergroups will be changed." msgstr "" -"Передайте True, чтобы изменить права администратора по умолчанию в каналах. " -"Иначе, будут изменены права администратора по умолчанию для групп и супергрупп." +"Передайте True, чтобы изменить права администратора по умолчанию в " +"каналах. Иначе, будут изменены права администратора по умолчанию для " +"групп и супергрупп." + +#: of telebot.async_telebot.AsyncTeleBot.set_my_description:1 +#, fuzzy +msgid "" +"Use this method to change the bot's description, which is shown in the " +"chat with the bot if the chat is empty. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы изменить кнопку меню в приватном чате или " +"кнопку меню по умолчанию. Возвращает True в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.set_my_description:5 +msgid "" +"New bot description; 0-512 characters. Pass an empty string to remove the" +" dedicated description for the given language." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_description:8 +#, fuzzy +msgid "" +"A two-letter ISO 639-1 language code. If empty, the description will be " +"applied to all users for whose language there is no dedicated " +"description." +msgstr "" +"Двухбуквенный языковой код в формате ISO 639-1. Если не задан, изменения " +"коснутся команд для всех пользователей в заданном поле видимости, не " +"имеющих команд на их языке" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:1 +#, fuzzy +msgid "Use this method to change the bot's name. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы изменить кнопку меню в приватном чате или " +"кнопку меню по умолчанию. Возвращает True в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:3 +#, fuzzy +msgid "Telegram documentation: https://core.telegram.org/bots/api#setmyname" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#sendgame" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:5 +msgid "" +"Optional. New bot name; 0-64 characters. Pass an empty string to remove " +"the dedicated name for the given language." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_name:8 +#, fuzzy +msgid "" +"Optional. A two-letter ISO 639-1 language code. If empty, the name will " +"be shown to all users for whose language there is no dedicated name." +msgstr "" +"Двухбуквенный языковой код в формате ISO 639-1. Если не задан, изменения " +"коснутся команд для всех пользователей в заданном поле видимости, не " +"имеющих команд на их языке" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_short_description:1 +msgid "" +"Use this method to change the bot's short description, which is shown on " +"the bot's profile page and is sent together with the link when users " +"share the bot. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_short_description:5 +msgid "" +"New short description for the bot; 0-120 characters. Pass an empty string" +" to remove the dedicated short description for the given language." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_my_short_description:8 +#, fuzzy +msgid "" +"A two-letter ISO 639-1 language code. If empty, the short description " +"will be applied to all users for whose language there is no dedicated " +"short description." +msgstr "" +"Двухбуквенный языковой код в формате ISO 639-1. Если не задан, изменения " +"коснутся команд для всех пользователей в заданном поле видимости, не " +"имеющих команд на их языке" #: of telebot.async_telebot.AsyncTeleBot.set_state:1 msgid "Sets a new state of a user." @@ -5126,21 +5440,73 @@ msgid "" "chat with a bot." msgstr "" "Вы должны указать и user id и chat id, чтобы задать состояние (стейт) " -"пользователя в чате. Иначе, если вы укажете только user_id, chat_id будет " -"равен user_id, что означает смену состояния (стейта) пользователя в его " +"пользователя в чате. Иначе, если вы укажете только user_id, chat_id будет" +" равен user_id, что означает смену состояния (стейта) пользователя в его " "приватном чате с ботом." #: of telebot.async_telebot.AsyncTeleBot.set_state:12 msgid "new state. can be string, integer, or :class:`telebot.types.State`" -msgstr "новое состояние (стейт). может быть строкой, числом или :class:`telebot.types.State`" +msgstr "" +"новое состояние (стейт). может быть строкой, числом или " +":class:`telebot.types.State`" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:1 +#, fuzzy +msgid "" +"Use this method to set the emoji list of a sticker set. Returns True on " +"success." +msgstr "" +"Используйте этот метод, чтобы удалить стикер из стикерпака, созданного " +"ботом. Возвращает True в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:7 +#, fuzzy +msgid "List of emojis" +msgstr "список апдейтов" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:1 +msgid "" +"Use this method to change search keywords assigned to a regular or custom" +" emoji sticker. The sticker must belong to a sticker set created by the " +"bot. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:5 +#: telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:5 +#, fuzzy +msgid "File identifier of the sticker." +msgstr "id файла стикера" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_keywords:8 +msgid "" +"A JSON-serialized list of 0-20 search keywords for the sticker with total" +" length of up to 64 characters" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:1 +#, fuzzy +msgid "" +"Use this method to change the mask position of a mask sticker. The " +"sticker must belong to a sticker set that was created by the bot. Returns" +" True on success." +msgstr "" +"Используйте этот метод, чтобы удалить стикер из стикерпака, созданного " +"ботом. Возвращает True в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_mask_position:8 +#, fuzzy +msgid "" +"A JSON-serialized object for position where the mask should be placed on " +"faces." +msgstr "Позиция для размещения маски на лицах в формате JSON" #: of telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:1 msgid "" "Use this method to move a sticker in a set created by the bot to a " "specific position . Returns True on success." msgstr "" -"Используйте этот метод, чтобы передвинуть стикер в стикерпаке, созданном ботом, на заданную " -"позицию. Возвращает True в случае успеха." +"Используйте этот метод, чтобы передвинуть стикер в стикерпаке, созданном " +"ботом, на заданную позицию. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:3 msgid "" @@ -5154,17 +5520,17 @@ msgstr "" msgid "New sticker position in the set, zero-based" msgstr "Новая позиция стикера в стикерпаке, начиная с нуля" -#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:1 +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:1 msgid "" "Use this method to set the thumbnail of a sticker set. Animated " "thumbnails can be set for animated sticker sets only. Returns True on " "success." msgstr "" "Используйте этот метод, чтобы задать обложку стикерпака. Анимированные " -"обложки могут быть заданы только для анимированных стикерпаков. Возвращает " -"True в случае успеха." +"обложки могут быть заданы только для анимированных стикерпаков. " +"Возвращает True в случае успеха." -#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumb:4 +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:4 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#setstickersetthumb" @@ -5172,9 +5538,44 @@ msgstr "" "Документация Telegram: " "https://core.telegram.org/bots/api#setstickersetthumb" +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:12 +msgid "" +"A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in " +"size and have a width and height of exactly 100px, or a .TGS animation " +"with a thumbnail up to 32 kilobytes in size (see " +"https://core.telegram.org/stickers#animated-sticker-requirements for " +"animated sticker technical requirements), or a WEBM video with the " +"thumbnail up to 32 kilobytes in size; see " +"https://core.telegram.org/stickers#video-sticker-requirements for video " +"sticker technical requirements. Pass a file_id as a String to send a file" +" that already exists on the Telegram servers, pass an HTTP URL as a " +"String for Telegram to get a file from the Internet, or upload a new one " +"using multipart/form-data. More information on Sending Files ». Animated " +"and video sticker set thumbnails can't be uploaded via HTTP URL. If " +"omitted, then the thumbnail is dropped and the first sticker is used as " +"the thumbnail." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:1 +#, fuzzy +msgid "" +"Use this method to set the title of a created sticker set. Returns True " +"on success." +msgstr "" +"Используйте этот метод, чтобы задать обложку стикерпака. Анимированные " +"обложки могут быть заданы только для анимированных стикерпаков. " +"Возвращает True в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.set_sticker_set_title:7 +#, fuzzy +msgid "New sticker set title" +msgstr "Имя стикерпака" + #: of telebot.async_telebot.AsyncTeleBot.set_update_listener:1 msgid "Update listener is a function that gets any update." -msgstr "Задаёт функцию-листенер, которая будет вызвана при получении нового апдейта." +msgstr "" +"Задаёт функцию-листенер, которая будет вызвана при получении нового " +"апдейта." #: of telebot.async_telebot.AsyncTeleBot.set_update_listener:3 msgid "function that should get update." @@ -5193,10 +5594,11 @@ msgid "" "reasonable amount of attempts. Returns True on success." msgstr "" "Используйте этот метод, чтобы задать URL и получать входящие апдейты с " -"помощью вебхука. Как только у бота появляется апдейт, он будет отправлен с " -"помощью HTTPS POST запроса на заданный URL, содержащего JSON-сериализованный " -"Update. В случае неудачного запроса, отправка апдейта будет отменена после " -"разумного числа попыток. Возвращает True в случае успеха." +"помощью вебхука. Как только у бота появляется апдейт, он будет отправлен " +"с помощью HTTPS POST запроса на заданный URL, содержащего " +"JSON-сериализованный Update. В случае неудачного запроса, отправка " +"апдейта будет отменена после разумного числа попыток. Возвращает True в " +"случае успеха." #: of telebot.async_telebot.AsyncTeleBot.set_webhook:6 msgid "" @@ -5206,8 +5608,8 @@ msgid "" "secret token as content." msgstr "" "Если вы хотите удостовериться, что вебхук был задан вами, вы можете " -"задать секретный токен в параметре secret_token. Если указан, запрос " -"с апдейтом будет содержать хедер “X-Telegram-Bot-Api-Secret-Token” с " +"задать секретный токен в параметре secret_token. Если указан, запрос с " +"апдейтом будет содержать хедер “X-Telegram-Bot-Api-Secret-Token” с " "секретным токеном в качестве значения." #: of telebot.async_telebot.AsyncTeleBot.set_webhook:9 @@ -5219,16 +5621,16 @@ msgid "" "HTTPS URL to send updates to. Use an empty string to remove webhook " "integration, defaults to None" msgstr "" -"HTTPS URL для отправки апдейтов. Используйте пустую строку, чтобы удалить " -"вебхук, по умолчанию None" +"HTTPS URL для отправки апдейтов. Используйте пустую строку, чтобы удалить" +" вебхук, по умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:14 msgid "" "Upload your public key certificate so that the root certificate in use " "can be checked, defaults to None" msgstr "" -"Загрузите публичный ключ вашего SSL сертификата, чтобы корневой сертификат мог быть " -"проверен, по умолчанию None" +"Загрузите публичный ключ вашего SSL сертификата, чтобы корневой " +"сертификат мог быть проверен, по умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:17 msgid "" @@ -5237,10 +5639,10 @@ msgid "" "limit the load on your bot's server, and higher values to increase your " "bot's throughput, defaults to None" msgstr "" -"Максимально-допустимое количество одновременных HTTPS соединений для доставки " -"апдейтов, 1-100. По умолчанию 40. Используйте меньшие значения для уменьшения " -"нагрузки на ваш сервер и большие значения, чтобы увеличить пропускную способность " -"вашего бота, по умолчанию None" +"Максимально-допустимое количество одновременных HTTPS соединений для " +"доставки апдейтов, 1-100. По умолчанию 40. Используйте меньшие значения " +"для уменьшения нагрузки на ваш сервер и большие значения, чтобы увеличить" +" пропускную способность вашего бота, по умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:22 msgid "" @@ -5257,10 +5659,11 @@ msgstr "" "Например, укажите [“message”, “edited_channel_post”, “callback_query”], " "чтобы получать апдейты только этих видов. Полный список доступных видов " "апдейтов - util.update_types. Укажите пустой список, чтобы получать все " -"апдейты, кроме chat_member (по умолчанию). Если не задан, будет использована " -"последняя настройка. Пожалуйста учтите, чтобы этот параметр не влияет на апдейты, " -"отправленные до вызова setWebhooks, поэтому нежелательные апдейты могут быть " -"получены в течение короткого периода времени. По умолчанию None" +"апдейты, кроме chat_member (по умолчанию). Если не задан, будет " +"использована последняя настройка. Пожалуйста учтите, чтобы этот параметр " +"не влияет на апдейты, отправленные до вызова setWebhooks, поэтому " +"нежелательные апдейты могут быть получены в течение короткого периода " +"времени. По умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:22 msgid "" @@ -5275,8 +5678,8 @@ msgstr "" "Например, укажите [“message”, “edited_channel_post”, “callback_query”], " "чтобы получать апдейты только этих видов. Полный список доступных видов " "апдейтов - util.update_types. Укажите пустой список, чтобы получать все " -"апдейты, кроме chat_member (по умолчанию). Если не задан, будет использована " -"последняя настройка." +"апдейты, кроме chat_member (по умолчанию). Если не задан, будет " +"использована последняя настройка." #: of telebot.async_telebot.AsyncTeleBot.set_webhook:27 msgid "" @@ -5284,17 +5687,18 @@ msgid "" " call to the setWebhook, so unwanted updates may be received for a short " "period of time. Defaults to None" msgstr "" -"Пожалуйста учтите, чтобы этот параметр не влияет на апдейты, " -"отправленные до вызова setWebhooks, поэтому нежелательные апдейты могут быть " -"получены в течение короткого периода времени. По умолчанию None" +"Пожалуйста учтите, чтобы этот параметр не влияет на апдейты, отправленные" +" до вызова setWebhooks, поэтому нежелательные апдейты могут быть получены" +" в течение короткого периода времени. По умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:32 msgid "" "The fixed IP address which will be used to send webhook requests instead " "of the IP address resolved through DNS, defaults to None" msgstr "" -"Фиксированный IP адрес, который будет использоваться для отправки запросов к вебхуку" -"вместо IP адреса, полученного с через DNS, по умолчанию None" +"Фиксированный IP адрес, который будет использоваться для отправки " +"запросов к вебхукувместо IP адреса, полученного с через DNS, по умолчанию" +" None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:42 msgid "" @@ -5303,10 +5707,10 @@ msgid "" "0-9, _ and - are allowed. The header is useful to ensure that the request" " comes from a webhook set by you. Defaults to None" msgstr "" -"Секретный токен для отправки в хедере “X-Telegram-Bot-Api-Secret-Token” " -"в каждом запросе с апдейтом, 1-256 символов. Разрешены только символы A-Z, a-z, " -"0-9, _ и -. Хедер полезен для, того чтобы удостовериться, что запрос приходит" -"с вебхука, установленного вами. По умолчанию None" +"Секретный токен для отправки в хедере “X-Telegram-Bot-Api-Secret-Token” в" +" каждом запросе с апдейтом, 1-256 символов. Разрешены только символы A-Z," +" a-z, 0-9, _ и -. Хедер полезен для, того чтобы удостовериться, что " +"запрос приходитс вебхука, установленного вами. По умолчанию None" #: of telebot.async_telebot.AsyncTeleBot.set_webhook:47 msgid ":obj:`bool` if the request was successful." @@ -5336,13 +5740,15 @@ msgid "" "price. As a parameter to the decorator function, it passes " ":class:`telebot.types.ShippingQuery` object." msgstr "" -"Обрабатывает shipping query. Только для инвойсов с гибкой ценой. " -"В качестве параметра передаёт в декорируемую функцию объект " +"Обрабатывает shipping query. Только для инвойсов с гибкой ценой. В " +"качестве параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.ShippingQuery`." #: of telebot.async_telebot.AsyncTeleBot.skip_updates:1 msgid "Skip existing updates. Only last update will remain on server." -msgstr "Пропускает существующие апдейты. На сервере останется только последний апдейт." +msgstr "" +"Пропускает существующие апдейты. На сервере останется только последний " +"апдейт." #: of telebot.async_telebot.AsyncTeleBot.stop_message_live_location:1 msgid "" @@ -5350,9 +5756,10 @@ msgid "" "live_period expires. On success, if the message is not an inline message," " the edited Message is returned, otherwise True is returned." msgstr "" -"Используйте этот метод, чтобы остановить обновление live местоположения до " -"истечения live_period. В случае успеха, если сообщение не является inline сообщением," -"возвращается измененное сообщение (Message), иначе возвращается True." +"Используйте этот метод, чтобы остановить обновление live местоположения " +"до истечения live_period. В случае успеха, если сообщение не является " +"inline сообщением,возвращается измененное сообщение (Message), иначе " +"возвращается True." #: of telebot.async_telebot.AsyncTeleBot.stop_message_live_location:4 msgid "" @@ -5367,32 +5774,32 @@ msgid "" "Required if inline_message_id is not specified. Identifier of the message" " with live location to stop" msgstr "" -"Обязательный, если не указан inline_message_id. id сообщения live местоположением, " -"которое нужно остановить" +"Обязательный, если не указан inline_message_id. id сообщения live " +"местоположением, которое нужно остановить" #: of telebot.async_telebot.AsyncTeleBot.stop_message_live_location:12 msgid "" "Required if chat_id and message_id are not specified. Identifier of the " "inline message with live location to stop" msgstr "" -"Обязательный, если не указаны chat_id и message_id. id inline сообщения с live " -"местоположением, которое нужно остановить" +"Обязательный, если не указаны chat_id и message_id. id inline сообщения с" +" live местоположением, которое нужно остановить" #: of telebot.async_telebot.AsyncTeleBot.stop_message_live_location:22 msgid "" "On success, if the message is not an inline message, the edited Message " "is returned, otherwise True is returned." msgstr "" -"В случае успеха, если сообщение не является inline сообщением, возвращается " -"измененное сообщение (Message), иначе возвращается True." +"В случае успеха, если сообщение не является inline сообщением, " +"возвращается измененное сообщение (Message), иначе возвращается True." #: of telebot.async_telebot.AsyncTeleBot.stop_poll:1 msgid "" "Use this method to stop a poll which was sent by the bot. On success, the" " stopped Poll is returned." msgstr "" -"Используйте этот метод, чтобы завершить опрос, отправленный ботом. В случае успеха " -"возвращается завершенный опрос (Poll)." +"Используйте этот метод, чтобы завершить опрос, отправленный ботом. В " +"случае успеха возвращается завершенный опрос (Poll)." #: of telebot.async_telebot.AsyncTeleBot.stop_poll:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#stoppoll" @@ -5425,11 +5832,12 @@ msgid "" " If you don't want this, use the parameter only_if_banned." msgstr "" "Используйте этот метод, чтобы разбанить ранее кикнутого пользователя в " -"супергруппе или канале. Пользовать не вернется в группу или канал автоматически, " -"но сможет присоединиться с помощью ссылки и т.д. Бот должен быть администратором. " -"По умолчанию, этот метод гарантирует, что после вызова, пользователь не является " -"участником чата, но может присоединиться. Поэтому если пользовать является участником " -"чата, он будет кикнут, но не забанен. Если вы хотите изменить это поведение, " +"супергруппе или канале. Пользовать не вернется в группу или канал " +"автоматически, но сможет присоединиться с помощью ссылки и т.д. Бот " +"должен быть администратором. По умолчанию, этот метод гарантирует, что " +"после вызова, пользователь не является участником чата, но может " +"присоединиться. Поэтому если пользовать является участником чата, он " +"будет кикнут, но не забанен. Если вы хотите изменить это поведение, " "используйте параметр only_if_banned." #: of telebot.async_telebot.AsyncTeleBot.unban_chat_member:7 @@ -5440,7 +5848,9 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#un msgid "" "Unique identifier for the target group or username of the target " "supergroup or channel (in the format @username)" -msgstr "Уникальный id группы или username супергруппы или канала (в формате @username)" +msgstr "" +"Уникальный id группы или username супергруппы или канала (в формате " +"@username)" #: of telebot.async_telebot.AsyncTeleBot.unban_chat_member:16 msgid "Do nothing if the user is not banned" @@ -5452,9 +5862,9 @@ msgid "" " or channel. The bot must be an administrator for this to work and must " "have the appropriate administrator rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы разбанить ране забаненный канал в супергруппе " -"или канала. Бот должен быть администратором и иметь соответствующие права " -"администратора. Возвращает True в случае успеха." +"Используйте этот метод, чтобы разбанить ране забаненный канал в " +"супергруппе или канала. Бот должен быть администратором и иметь " +"соответствующие права администратора. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:6 msgid "" @@ -5469,18 +5879,16 @@ msgid "Unique identifier of the target sender chat." msgstr "Уникальный id чата." #: of telebot.async_telebot.AsyncTeleBot.unhide_general_forum_topic:1 - msgid "" "Use this method to unhide the 'General' topic in a forum supergroup chat." " The bot must be an administrator in the chat for this to work and must " "have can_manage_topics administrator rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы сделать топик 'General' видимым в супергруппе " -"с топиками. Бот должен быть администратором чата и иметь права администратора " -"can_manage_topics. Возвращает True в случае успеха." +"Используйте этот метод, чтобы сделать топик 'General' видимым в " +"супергруппе с топиками. Бот должен быть администратором чата и иметь " +"права администратора can_manage_topics. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.unhide_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#unhidegeneralforumtopic" @@ -5494,9 +5902,9 @@ msgid "" "bot must be an administrator in the chat for this to work and must have " "the appropriate admin rights. Returns True on success." msgstr "" -"Используйте этот метод, что открепить все закрепленные сообщения в супергруппе. " -"Бот должен быть администратором чата и иметь соответствующие права администратора. " -"Возвращает True в случае успеха." +"Используйте этот метод, что открепить все закрепленные сообщения в " +"супергруппе. Бот должен быть администратором чата и иметь соответствующие" +" права администратора. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:5 msgid "" @@ -5513,9 +5921,9 @@ msgid "" "have the can_pin_messages administrator right in the supergroup. Returns " "True on success." msgstr "" -"Используйте этот метод, что открепить все закрепленные сообщения в топике. " -"Бот должен быть администратором чата и иметь права администратора " -"can_pin_messages в супергруппе. Возвращает True в случае успеха." +"Используйте этот метод, что открепить все закрепленные сообщения в " +"топике. Бот должен быть администратором чата и иметь права администратора" +" can_pin_messages в супергруппе. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:5 msgid "" @@ -5535,17 +5943,15 @@ msgid "" "The bot must be an administrator in the chat for this to work and must " "have the appropriate admin rights. Returns True on success." msgstr "" -"Используйте этот метод, что открепить закрепленное сообщение в супергруппе. " -"Бот должен быть администратором чата и иметь соответствующие права администратора. " -"Возвращает True в случае успеха." +"Используйте этот метод, что открепить закрепленное сообщение в " +"супергруппе. Бот должен быть администратором чата и иметь соответствующие" +" права администратора. Возвращает True в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.unpin_chat_message:5 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#unpinchatmessage" -msgstr "" -"Документация Telegram: " -"https://core.telegram.org/bots/api#unpinchatmessage" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#unpinchatmessage" #: of telebot.async_telebot.AsyncTeleBot.unpin_chat_message:11 msgid "Int: Identifier of a message to unpin" @@ -5559,7 +5965,8 @@ msgid "" msgstr "" "Используйте этот метод, чтобы загрузить .png стикер, чтобы позже " "использовать в методах createNewStickerSet и addStickerToSet (может быть " -"использован несколько раз). Возвращает загруженный файл (File) в случае успеха." +"использован несколько раз). Возвращает загруженный файл (File) в случае " +"успеха." #: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:4 msgid "" @@ -5574,15 +5981,28 @@ msgid "User identifier of sticker set owner" msgstr "id пользователя, создавшего стикерпак" #: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:9 +#, fuzzy msgid "" -"PNG image with the sticker, must be up to 512 kilobytes in size, " -"dimensions must not exceed 512px, and either width or height must be " -"exactly 512px." +"DEPRECATED: PNG image with the sticker, must be up to 512 kilobytes in " +"size, dimensions must not exceed 512px, and either width or height must " +"be exactly 512px." msgstr "" "PNG изображение стикера, должно весить не более 512 kB, измерения не " -"должны превышать 512px и либо ширина, либо высота должна быть ровно 512px." +"должны превышать 512px и либо ширина, либо высота должна быть ровно " +"512px." #: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:13 +msgid "" +"A file with the sticker in .WEBP, .PNG, .TGS, or .WEBM format. See " +"https://core.telegram.org/stickers for technical requirements. More " +"information on Sending Files »" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:17 +msgid "One of \"static\", \"animated\", \"video\"." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.upload_sticker_file:20 msgid "On success, the sent file is returned." msgstr "В случае успеха возвращается отправленный файл." @@ -5610,9 +6030,10 @@ msgid "" " - filter failed. message: Message class text: Filter value given in " "handler" msgstr "" -"Базовый класс Advanced Custom Filter. Создайте класс наследник с методом check(). " -"Принимает два параметра, возвращает bool: True - фильтр пройден, False - фильтр " -"не пройден. message: класс Message text: значение фильтра, полученное в хендлере" +"Базовый класс Advanced Custom Filter. Создайте класс наследник с методом " +"check(). Принимает два параметра, возвращает bool: True - фильтр пройден," +" False - фильтр не пройден. message: класс Message text: значение " +"фильтра, полученное в хендлере" #: of telebot.asyncio_filters.AdvancedCustomFilter:7 #: telebot.asyncio_filters.SimpleCustomFilter:5 @@ -5687,8 +6108,9 @@ msgid "" "Accepts only message, returns bool value, that is compared with given in " "handler." msgstr "" -"Базовый класс Simple Custom Filter. Создайте класс наследник с методом check(). " -"Принимает только сообщение, возвращает bool, который сравнивается с заданным в хендлере." +"Базовый класс Simple Custom Filter. Создайте класс наследник с методом " +"check(). Принимает только сообщение, возвращает bool, который " +"сравнивается с заданным в хендлере." #: of telebot.asyncio_filters.SimpleCustomFilter:7 msgid "Example on creating a simple custom filter." @@ -5707,8 +6129,8 @@ msgid "" "Advanced text filter to check (types.Message, types.CallbackQuery, " "types.InlineQuery, types.Poll)" msgstr "" -"Advanced текстовый фильтр для проверки (types.Message, types.CallbackQuery, " -"types.InlineQuery, types.Poll)" +"Advanced текстовый фильтр для проверки (types.Message, " +"types.CallbackQuery, types.InlineQuery, types.Poll)" #: of telebot.asyncio_filters.TextFilter:3 msgid "" @@ -5724,7 +6146,9 @@ msgstr "строка, True если текст объекта идентичен #: of telebot.asyncio_filters.TextFilter:8 msgid "list[str] or tuple[str], True if any string element of iterable is in text" -msgstr "list[str] или tuple[str], True если хотя бы один из элементов есть в тексте" +msgstr "" +"list[str] или tuple[str], True если хотя бы один из элементов есть в " +"тексте" #: of telebot.asyncio_filters.TextFilter:11 #: telebot.asyncio_filters.TextFilter:14 @@ -5764,8 +6188,8 @@ msgid "" "Base class for middleware. Your middlewares should be inherited from this" " class." msgstr "" -"Базовый класс для middleware. Ваши middleware должны быть унаследованы от " -"этого класса." +"Базовый класс для middleware. Ваши middleware должны быть унаследованы от" +" этого класса." #: of telebot.asyncio_handler_backends.BaseMiddleware:4 msgid "" @@ -5776,8 +6200,8 @@ msgid "" msgstr "" "Задайте update_sensitive=True если хотите получать разные апдейты в " "разных функциях. Например, если вы хотите обрабатывать pre_process для " -"апдейтов вида message, вам нужно будет создать функцию pre_process_message " -"и т.д. Аналогично для post_process." +"апдейтов вида message, вам нужно будет создать функцию " +"pre_process_message и т.д. Аналогично для post_process." #: of telebot.asyncio_handler_backends.BaseMiddleware:9 msgid "Example of class-based middlewares" @@ -5790,16 +6214,16 @@ msgid "" "post_process in middlewares." msgstr "" "Класс для отмены апдейтов. Просто верните экземпляр этого класса в " -"middleware, чтобы пропустить апдейт. Апдейт пропустит хендлер и исполнение " -"post_process в middleware." +"middleware, чтобы пропустить апдейт. Апдейт пропустит хендлер и " +"исполнение post_process в middleware." #: of telebot.asyncio_handler_backends.ContinueHandling:1 msgid "" "Class for continue updates in handlers. Just return instance of this " "class in handlers to continue process." msgstr "" -"Класс для продолжения обработки апдейта в хендлерах. Просто верните экземпляр " -"этого класса в хендлерах, чтобы продолжить обработку." +"Класс для продолжения обработки апдейта в хендлерах. Просто верните " +"экземпляр этого класса в хендлерах, чтобы продолжить обработку." #: of telebot.asyncio_handler_backends.ContinueHandling:5 msgid "Example of using ContinueHandling" @@ -5833,15 +6257,17 @@ msgstr "Этот файл используется функцией AsyncTeleBot #: of telebot.ext.aio.webhooks:3 msgid "Fastapi and starlette(0.20.2+) libraries are required to run this script." -msgstr "Для запуска этого скрипта требуются библиотеки Fastapi и starlette(0.20.2+)." +msgstr "" +"Для запуска этого скрипта требуются библиотеки Fastapi и " +"starlette(0.20.2+)." #: of telebot.ext.aio.webhooks.AsyncWebhookListener.run_app:1 msgid "" "Run app with the given parameters to init. Not supposed to be used " "manually by user." msgstr "" -"Запустить приложение с заданными параметрами инициализации. Не предназначено " -"для использования пользователем." +"Запустить приложение с заданными параметрами инициализации. Не " +"предназначено для использования пользователем." #~ msgid "New name of the topic, 1-128 characters" #~ msgstr "Новое название топика, 1-128 символов" @@ -5862,3 +6288,20 @@ msgstr "" #~ ":meth:`telebot.async_telebot.AsyncTeleBot.send_message`" #~ msgstr "" +#~ msgid "" +#~ "Use this method to add a new " +#~ "sticker to a set created by the" +#~ " bot. It's required to pass " +#~ "`png_sticker` or `tgs_sticker`. Returns True" +#~ " on success." +#~ msgstr "" +#~ "Используйте этот метод, чтобы добавить " +#~ "новый стикер в стикерпак, созданный " +#~ "ботом. Необходимо передать либо `png_sticker`," +#~ " либо `tgs_sticker`, либо `webm_sticker`. " +#~ "Возвращает True в случае успешного " +#~ "добавления." + +#~ msgid "Timeout in seconds for long polling." +#~ msgstr "Тайм-аут поллинга в секундах." + diff --git a/docs/source/locales/ru/LC_MESSAGES/sync_version.po b/docs/source/locales/ru/LC_MESSAGES/sync_version.po index 3858e743f..c9243db70 100644 --- a/docs/source/locales/ru/LC_MESSAGES/sync_version.po +++ b/docs/source/locales/ru/LC_MESSAGES/sync_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-02 19:24+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -115,9 +115,9 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands #: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file -#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic -#: telebot.TeleBot.edit_general_forum_topic +#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook +#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link +#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_general_forum_topic #: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup @@ -134,16 +134,17 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.get_file_url telebot.TeleBot.get_game_high_scores #: telebot.TeleBot.get_my_commands #: telebot.TeleBot.get_my_default_administrator_rights -#: telebot.TeleBot.get_state telebot.TeleBot.get_sticker_set -#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_profile_photos -#: telebot.TeleBot.get_webhook_info telebot.TeleBot.hide_general_forum_topic -#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler -#: telebot.TeleBot.leave_chat telebot.TeleBot.load_next_step_handlers -#: telebot.TeleBot.load_reply_handlers telebot.TeleBot.message_handler -#: telebot.TeleBot.middleware_handler telebot.TeleBot.my_chat_member_handler -#: telebot.TeleBot.pin_chat_message telebot.TeleBot.poll_answer_handler -#: telebot.TeleBot.poll_handler telebot.TeleBot.polling -#: telebot.TeleBot.pre_checkout_query_handler +#: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name +#: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state +#: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates +#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info +#: telebot.TeleBot.hide_general_forum_topic telebot.TeleBot.infinity_polling +#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat +#: telebot.TeleBot.load_next_step_handlers telebot.TeleBot.load_reply_handlers +#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message +#: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler +#: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.process_new_updates telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler @@ -176,16 +177,21 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.send_media_group telebot.TeleBot.send_message #: telebot.TeleBot.send_photo telebot.TeleBot.send_poll #: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note -#: telebot.TeleBot.send_voice +#: telebot.TeleBot.send_video telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights -#: telebot.TeleBot.set_state telebot.TeleBot.set_sticker_position_in_set -#: telebot.TeleBot.set_sticker_set_thumb telebot.TeleBot.set_update_listener +#: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name +#: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state +#: telebot.TeleBot.set_sticker_emoji_list telebot.TeleBot.set_sticker_keywords +#: telebot.TeleBot.set_sticker_mask_position +#: telebot.TeleBot.set_sticker_position_in_set +#: telebot.TeleBot.set_sticker_set_thumbnail +#: telebot.TeleBot.set_sticker_set_title telebot.TeleBot.set_update_listener #: telebot.TeleBot.set_webhook telebot.TeleBot.setup_middleware #: telebot.TeleBot.shipping_query_handler #: telebot.TeleBot.stop_message_live_location telebot.TeleBot.stop_poll @@ -322,9 +328,9 @@ msgstr "Данные для добавления" #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands #: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file -#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic -#: telebot.TeleBot.edit_message_caption +#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook +#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link +#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text @@ -339,15 +345,16 @@ msgstr "Данные для добавления" #: telebot.TeleBot.get_file_url telebot.TeleBot.get_forum_topic_icon_stickers #: telebot.TeleBot.get_game_high_scores telebot.TeleBot.get_my_commands #: telebot.TeleBot.get_my_default_administrator_rights -#: telebot.TeleBot.get_state telebot.TeleBot.get_sticker_set -#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_profile_photos -#: telebot.TeleBot.get_webhook_info telebot.TeleBot.infinity_polling -#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat -#: telebot.TeleBot.log_out telebot.TeleBot.message_handler -#: telebot.TeleBot.middleware_handler telebot.TeleBot.my_chat_member_handler -#: telebot.TeleBot.pin_chat_message telebot.TeleBot.poll_answer_handler -#: telebot.TeleBot.poll_handler telebot.TeleBot.polling -#: telebot.TeleBot.pre_checkout_query_handler +#: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name +#: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state +#: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates +#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info +#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler +#: telebot.TeleBot.leave_chat telebot.TeleBot.log_out +#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message +#: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler +#: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler @@ -378,16 +385,21 @@ msgstr "Данные для добавления" #: telebot.TeleBot.send_media_group telebot.TeleBot.send_message #: telebot.TeleBot.send_photo telebot.TeleBot.send_poll #: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note -#: telebot.TeleBot.send_voice +#: telebot.TeleBot.send_video telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights -#: telebot.TeleBot.set_state telebot.TeleBot.set_sticker_position_in_set -#: telebot.TeleBot.set_sticker_set_thumb telebot.TeleBot.set_webhook +#: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name +#: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state +#: telebot.TeleBot.set_sticker_emoji_list telebot.TeleBot.set_sticker_keywords +#: telebot.TeleBot.set_sticker_mask_position +#: telebot.TeleBot.set_sticker_position_in_set +#: telebot.TeleBot.set_sticker_set_thumbnail +#: telebot.TeleBot.set_sticker_set_title telebot.TeleBot.set_webhook #: telebot.TeleBot.setup_middleware telebot.TeleBot.shipping_query_handler #: telebot.TeleBot.stop_message_live_location telebot.TeleBot.stop_poll #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat @@ -437,35 +449,43 @@ msgstr "" #: of telebot.TeleBot.add_sticker_to_set:1 msgid "" -"Use this method to add a new sticker to a set created by the bot. It's " -"required to pass `png_sticker` or `tgs_sticker`. Returns True on success." +"Use this method to add a new sticker to a set created by the bot. The " +"format of the added sticker must match the format of the other stickers " +"in the set. Emoji sticker sets can have up to 200 stickers. Animated and " +"video sticker sets can have up to 50 stickers. Static sticker sets can " +"have up to 120 stickers. Returns True on success." msgstr "" -"Используйте этот метод, чтобы добавить новый стикер в стикерпак, " -"созданный ботом. Необходимо передать либо `png_sticker`, либо " -"`tgs_sticker`, либо `webm_sticker`. Возвращает True в случае успешного " -"добавления." -#: of telebot.TeleBot.add_sticker_to_set:5 +#: of telebot.TeleBot.add_sticker_to_set:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#addstickertoset" msgstr "Документация Telegram: https://core.telegram.org/bots/api#addstickertoset" -#: of telebot.TeleBot.add_sticker_to_set:7 -#: telebot.TeleBot.create_new_sticker_set:7 +#: of telebot.TeleBot.add_sticker_to_set:10 +msgid "" +"**_sticker, mask_position, emojis parameters are deprecated, use stickers" +" instead" +msgstr "" + +#: of telebot.TeleBot.add_sticker_to_set:12 +#: telebot.TeleBot.create_new_sticker_set:10 msgid "User identifier of created sticker set owner" msgstr "id пользователя, создавшего стикерпак" -#: of telebot.TeleBot.add_sticker_to_set:10 telebot.TeleBot.get_sticker_set:5 -#: telebot.TeleBot.set_sticker_set_thumb:6 +#: of telebot.TeleBot.add_sticker_to_set:15 +#: telebot.TeleBot.delete_sticker_set:3 telebot.TeleBot.get_sticker_set:5 +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:4 +#: telebot.TeleBot.set_sticker_set_thumbnail:6 +#: telebot.TeleBot.set_sticker_set_title:4 msgid "Sticker set name" msgstr "Имя стикерпака" -#: of telebot.TeleBot.add_sticker_to_set:13 -#: telebot.TeleBot.create_new_sticker_set:18 +#: of telebot.TeleBot.add_sticker_to_set:18 +#: telebot.TeleBot.create_new_sticker_set:21 msgid "One or more emoji corresponding to the sticker" msgstr "Один или несколько эмодзи, относящихся к стикеру" -#: of telebot.TeleBot.add_sticker_to_set:16 -#: telebot.TeleBot.create_new_sticker_set:21 +#: of telebot.TeleBot.add_sticker_to_set:21 +#: telebot.TeleBot.create_new_sticker_set:24 msgid "" "PNG image with the sticker, must be up to 512 kilobytes in size, " "dimensions must not exceed 512px, and either width or height must be " @@ -481,39 +501,46 @@ msgstr "" "Telegram скачал файл из интернета, или загрузите новый файл с помощью " "multipart/form-data." -#: of telebot.TeleBot.add_sticker_to_set:21 -#: telebot.TeleBot.create_new_sticker_set:26 +#: of telebot.TeleBot.add_sticker_to_set:26 +#: telebot.TeleBot.create_new_sticker_set:29 msgid "TGS animation with the sticker, uploaded using multipart/form-data." msgstr "" "Анимированный стикер в формате TGS, загруженный с помощью multipart/form-" "data." -#: of telebot.TeleBot.add_sticker_to_set:24 -#: telebot.TeleBot.create_new_sticker_set:29 +#: of telebot.TeleBot.add_sticker_to_set:29 +#: telebot.TeleBot.create_new_sticker_set:32 msgid "WebM animation with the sticker, uploaded using multipart/form-data." msgstr "" "Анимированный стикер в формате WebM, загруженный с помощью multipart" "/form-data." -#: of telebot.TeleBot.add_sticker_to_set:27 -#: telebot.TeleBot.create_new_sticker_set:40 +#: of telebot.TeleBot.add_sticker_to_set:32 +#: telebot.TeleBot.create_new_sticker_set:42 msgid "" "A JSON-serialized object for position where the mask should be placed on " "faces" msgstr "Позиция для размещения маски на лицах в формате JSON" -#: of telebot.TeleBot.add_sticker_to_set:30 +#: of telebot.TeleBot.add_sticker_to_set:35 +msgid "" +"A JSON-serialized list of 1-50 initial stickers to be added to the " +"sticker set" +msgstr "" + +#: of telebot.TeleBot.add_sticker_to_set:38 #: telebot.TeleBot.answer_callback_query:22 -#: telebot.TeleBot.answer_inline_query:35 +#: telebot.TeleBot.answer_inline_query:38 #: telebot.TeleBot.answer_pre_checkout_query:21 #: telebot.TeleBot.answer_shipping_query:18 #: telebot.TeleBot.close_forum_topic:13 -#: telebot.TeleBot.create_new_sticker_set:43 +#: telebot.TeleBot.create_new_sticker_set:56 #: telebot.TeleBot.delete_forum_topic:13 #: telebot.TeleBot.delete_sticker_from_set:6 #: telebot.TeleBot.edit_forum_topic:22 telebot.TeleBot.reopen_forum_topic:13 +#: telebot.TeleBot.set_sticker_keywords:11 #: telebot.TeleBot.set_sticker_position_in_set:11 -#: telebot.TeleBot.set_sticker_set_thumb:15 +#: telebot.TeleBot.set_sticker_set_thumbnail:15 #: telebot.TeleBot.unpin_all_forum_topic_messages:13 msgid "On success, True is returned." msgstr "В случае успеха возвращается True." @@ -530,9 +557,10 @@ msgstr "В случае успеха возвращается True." #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands -#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_webhook -#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link -#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_message_caption +#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_sticker_set +#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file +#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic +#: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text telebot.TeleBot.export_chat_invite_link @@ -558,15 +586,18 @@ msgstr "В случае успеха возвращается True." #: telebot.TeleBot.send_message telebot.TeleBot.send_photo #: telebot.TeleBot.send_poll telebot.TeleBot.send_sticker #: telebot.TeleBot.send_venue telebot.TeleBot.send_video -#: telebot.TeleBot.send_video_note #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights +#: telebot.TeleBot.set_sticker_emoji_list telebot.TeleBot.set_sticker_keywords +#: telebot.TeleBot.set_sticker_mask_position #: telebot.TeleBot.set_sticker_position_in_set -#: telebot.TeleBot.set_sticker_set_thumb telebot.TeleBot.set_webhook +#: telebot.TeleBot.set_sticker_set_thumbnail +#: telebot.TeleBot.set_sticker_set_title telebot.TeleBot.set_webhook #: telebot.TeleBot.stop_message_live_location telebot.TeleBot.stop_poll #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat #: telebot.TeleBot.unpin_all_chat_messages @@ -576,34 +607,43 @@ msgstr "В случае успеха возвращается True." msgid "Return type" msgstr "" -#: of telebot.TeleBot.add_sticker_to_set:31 +#: of telebot.TeleBot.add_sticker_to_set:39 #: telebot.TeleBot.answer_callback_query:23 -#: telebot.TeleBot.answer_inline_query:36 +#: telebot.TeleBot.answer_inline_query:39 #: telebot.TeleBot.answer_pre_checkout_query:22 #: telebot.TeleBot.answer_shipping_query:19 #: telebot.TeleBot.approve_chat_join_request:15 #: telebot.TeleBot.ban_chat_member:25 telebot.TeleBot.ban_chat_sender_chat:17 #: telebot.TeleBot.close:9 telebot.TeleBot.close_forum_topic:14 -#: telebot.TeleBot.create_new_sticker_set:44 +#: telebot.TeleBot.create_new_sticker_set:57 #: telebot.TeleBot.decline_chat_join_request:15 #: telebot.TeleBot.delete_chat_photo:13 #: telebot.TeleBot.delete_chat_sticker_set:11 #: telebot.TeleBot.delete_forum_topic:14 telebot.TeleBot.delete_message:23 #: telebot.TeleBot.delete_my_commands:17 -#: telebot.TeleBot.delete_sticker_from_set:7 telebot.TeleBot.delete_webhook:13 +#: telebot.TeleBot.delete_sticker_from_set:7 +#: telebot.TeleBot.delete_sticker_set:7 telebot.TeleBot.delete_webhook:13 #: telebot.TeleBot.edit_forum_topic:23 telebot.TeleBot.leave_chat:8 #: telebot.TeleBot.log_out:11 telebot.TeleBot.pin_chat_message:19 #: telebot.TeleBot.promote_chat_member:61 telebot.TeleBot.remove_webhook:4 #: telebot.TeleBot.reopen_forum_topic:14 -#: telebot.TeleBot.restrict_chat_member:48 telebot.TeleBot.send_chat_action:26 +#: telebot.TeleBot.restrict_chat_member:61 telebot.TeleBot.send_chat_action:26 +#: telebot.TeleBot.send_video_note:28 telebot.TeleBot.send_video_note:40 +#: telebot.TeleBot.send_video_note:43 #: telebot.TeleBot.set_chat_administrator_custom_title:18 #: telebot.TeleBot.set_chat_description:14 #: telebot.TeleBot.set_chat_menu_button:15 -#: telebot.TeleBot.set_chat_permissions:15 telebot.TeleBot.set_chat_photo:16 -#: telebot.TeleBot.set_chat_title:17 telebot.TeleBot.set_my_commands:18 +#: telebot.TeleBot.set_chat_permissions:21 telebot.TeleBot.set_chat_photo:16 +#: telebot.TeleBot.set_chat_title:17 +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:11 +#: telebot.TeleBot.set_my_commands:18 #: telebot.TeleBot.set_my_default_administrator_rights:18 +#: telebot.TeleBot.set_sticker_emoji_list:11 +#: telebot.TeleBot.set_sticker_keywords:12 +#: telebot.TeleBot.set_sticker_mask_position:12 #: telebot.TeleBot.set_sticker_position_in_set:12 -#: telebot.TeleBot.set_sticker_set_thumb:16 +#: telebot.TeleBot.set_sticker_set_thumbnail:16 +#: telebot.TeleBot.set_sticker_set_title:11 #: telebot.TeleBot.unban_chat_member:20 #: telebot.TeleBot.unban_chat_sender_chat:15 #: telebot.TeleBot.unpin_all_chat_messages:12 @@ -705,8 +745,8 @@ msgid "" "The maximum amount of time in seconds that the result of the inline query" " may be cached on the server." msgstr "" -"Максимальная длительность хранения результатов inline query на сервере " -"в секундах." +"Максимальная длительность хранения результатов inline query на сервере в " +"секундах." #: of telebot.TeleBot.answer_inline_query:16 msgid "" @@ -759,6 +799,13 @@ msgstr "" "Параметр для передачи боту вместе с сообщением /start, отправленному при " "нажатии кнопки переключения" +#: of telebot.TeleBot.answer_inline_query:35 +#, fuzzy +msgid "" +"A JSON-serialized object describing a button to be shown above inline " +"query results" +msgstr "Объект в формате JSON, описывающий сообщение, которое нужно отправить" + #: of telebot.TeleBot.answer_pre_checkout_query:1 msgid "" "Once the user has confirmed their payment and shipping details, the Bot " @@ -922,7 +969,7 @@ msgstr "" #: telebot.TeleBot.decline_chat_join_request:11 #: telebot.TeleBot.get_chat_member:8 telebot.TeleBot.get_user_profile_photos:6 #: telebot.TeleBot.promote_chat_member:11 -#: telebot.TeleBot.restrict_chat_member:11 +#: telebot.TeleBot.restrict_chat_member:14 #: telebot.TeleBot.set_chat_administrator_custom_title:10 #: telebot.TeleBot.unban_chat_member:13 msgid "Unique identifier of the target user" @@ -939,7 +986,9 @@ msgstr "Уникальный id сделавшего запрос пользов #: telebot.TeleBot.set_chat_menu_button:14 telebot.TeleBot.set_chat_photo:15 #: telebot.TeleBot.set_chat_title:16 telebot.TeleBot.set_my_commands:17 #: telebot.TeleBot.set_my_default_administrator_rights:17 -#: telebot.TeleBot.set_webhook:46 telebot.TeleBot.unban_chat_sender_chat:14 +#: telebot.TeleBot.set_my_description:14 telebot.TeleBot.set_my_name:12 +#: telebot.TeleBot.set_my_short_description:14 telebot.TeleBot.set_webhook:46 +#: telebot.TeleBot.unban_chat_sender_chat:14 #: telebot.TeleBot.unpin_all_chat_messages:11 #: telebot.TeleBot.unpin_chat_message:14 msgid "True on success." @@ -961,7 +1010,7 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#banchatmember" msgstr "Документация Telegram: https://core.telegram.org/bots/api#banchatmember" -#: of telebot.TeleBot.ban_chat_member:8 telebot.TeleBot.restrict_chat_member:7 +#: of telebot.TeleBot.ban_chat_member:8 telebot.TeleBot.restrict_chat_member:10 msgid "" "Unique identifier for the target group or username of the target " "supergroup or channel (in the format @channelusername)" @@ -992,7 +1041,12 @@ msgstr "" #: of telebot.TeleBot.ban_chat_member:24 #: telebot.TeleBot.delete_chat_sticker_set:10 telebot.TeleBot.delete_message:22 -#: telebot.TeleBot.delete_webhook:12 telebot.TeleBot.send_chat_action:25 +#: telebot.TeleBot.delete_sticker_set:6 telebot.TeleBot.delete_webhook:12 +#: telebot.TeleBot.send_chat_action:25 +#: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:10 +#: telebot.TeleBot.set_sticker_emoji_list:10 +#: telebot.TeleBot.set_sticker_mask_position:11 +#: telebot.TeleBot.set_sticker_set_title:10 msgid "Returns True on success." msgstr "Возвращает True в случае успеха." @@ -1179,9 +1233,9 @@ msgid "" "parameter to the decorator function, it passes " ":class:`telebot.types.ChosenInlineResult` object." msgstr "" -"Обрабатывает результат inline query, который был выбран пользователем и" -" отправлен собеседнику в чате. Пожалуйста ознакомьтесь с документацией по" -" сбору фидбека для получения таких апдейтов вашим ботом. В качестве " +"Обрабатывает результат inline query, который был выбран пользователем и " +"отправлен собеседнику в чате. Пожалуйста ознакомьтесь с документацией по " +"сбору фидбека для получения таких апдейтов вашим ботом. В качестве " "параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.ChosenInlineResult`." @@ -1258,7 +1312,6 @@ msgid "Identifier of the topic to close" msgstr "id топика для закрытия" #: of telebot.TeleBot.close_general_forum_topic:1 - msgid "" "Use this method to close the 'General' topic in a forum supergroup chat. " "The bot must be an administrator in the chat for this to work and must " @@ -1270,7 +1323,6 @@ msgstr "" "топика. Возвращает True в случае успеха." #: of telebot.TeleBot.close_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#closegeneralforumtopic" @@ -1407,26 +1459,24 @@ msgid "Identifier of a message thread, in which the message will be sent" msgstr "id топика, в который нужно отправить сообщение" #: of telebot.TeleBot.copy_message:45 telebot.TeleBot.forward_message:26 -#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:63 -#: telebot.TeleBot.send_audio:63 telebot.TeleBot.send_contact:44 -#: telebot.TeleBot.send_dice:35 telebot.TeleBot.send_document:56 +#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:66 +#: telebot.TeleBot.send_audio:66 telebot.TeleBot.send_contact:44 +#: telebot.TeleBot.send_dice:35 telebot.TeleBot.send_document:59 #: telebot.TeleBot.send_game:32 telebot.TeleBot.send_invoice:101 #: telebot.TeleBot.send_location:49 telebot.TeleBot.send_message:46 #: telebot.TeleBot.send_photo:48 telebot.TeleBot.send_poll:70 -#: telebot.TeleBot.send_sticker:39 telebot.TeleBot.send_venue:57 -#: telebot.TeleBot.send_video:64 telebot.TeleBot.send_video_note:48 -#: telebot.TeleBot.send_voice:49 +#: telebot.TeleBot.send_sticker:42 telebot.TeleBot.send_venue:57 +#: telebot.TeleBot.send_video:67 telebot.TeleBot.send_voice:49 msgid "On success, the sent Message is returned." msgstr "В случае успеха возвращает отправленное сообщение (Message)." #: of telebot.TeleBot.copy_message:46 telebot.TeleBot.forward_message:27 -#: telebot.TeleBot.reply_to:12 telebot.TeleBot.send_animation:64 -#: telebot.TeleBot.send_audio:64 telebot.TeleBot.send_contact:45 -#: telebot.TeleBot.send_dice:36 telebot.TeleBot.send_document:57 +#: telebot.TeleBot.reply_to:12 telebot.TeleBot.send_animation:67 +#: telebot.TeleBot.send_audio:67 telebot.TeleBot.send_contact:45 +#: telebot.TeleBot.send_dice:36 telebot.TeleBot.send_document:60 #: telebot.TeleBot.send_location:50 telebot.TeleBot.send_message:47 -#: telebot.TeleBot.send_photo:49 telebot.TeleBot.send_sticker:40 -#: telebot.TeleBot.send_venue:58 telebot.TeleBot.send_video:65 -#: telebot.TeleBot.send_video_note:49 +#: telebot.TeleBot.send_photo:49 telebot.TeleBot.send_sticker:43 +#: telebot.TeleBot.send_venue:58 telebot.TeleBot.send_video:68 msgid ":class:`telebot.types.Message`" msgstr "" @@ -1438,10 +1488,11 @@ msgid "" "method revokeChatInviteLink. Returns the new invite link as " "ChatInviteLink object." msgstr "" -"Используйте этот метод, чтобы создать дополнительную ссылку-приглашение в чат. Бот " -"должен быть администратором чата и иметь соответствующие права администратора. " -"Ссылка может быть аннулирована методом revokeChatInviteLink. Возвращает новую " -"ссылку-приглашение (ChatInviteLink)." +"Используйте этот метод, чтобы создать дополнительную ссылку-приглашение в" +" чат. Бот должен быть администратором чата и иметь соответствующие права " +"администратора. Ссылка может быть аннулирована методом " +"revokeChatInviteLink. Возвращает новую ссылку-приглашение " +"(ChatInviteLink)." #: of telebot.TeleBot.create_chat_invite_link:6 msgid "" @@ -1705,7 +1756,13 @@ msgstr "" "Документация Telegram: " "https://core.telegram.org/bots/api#createnewstickerset" -#: of telebot.TeleBot.create_new_sticker_set:10 +#: of telebot.TeleBot.create_new_sticker_set:8 +msgid "" +"Fields *_sticker are deprecated, pass a list of stickers to stickers " +"parameter instead." +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:13 msgid "" "Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., " "animals). Can contain only English letters, digits and underscores. Must " @@ -1719,11 +1776,11 @@ msgstr "" "содержать подряд идущие нижние подчеркивания и должно заканчиваться на " "\"_by_\". учитывает регистр. 1-64 символа." -#: of telebot.TeleBot.create_new_sticker_set:15 +#: of telebot.TeleBot.create_new_sticker_set:18 msgid "Sticker set title, 1-64 characters" msgstr "Название стикерпака, 1-64 символа" -#: of telebot.TeleBot.create_new_sticker_set:32 +#: of telebot.TeleBot.create_new_sticker_set:35 msgid "" "Pass True, if a set of mask stickers should be created. Deprecated since " "Bot API 6.2, use sticker_type instead." @@ -1731,16 +1788,34 @@ msgstr "" "Передайте True, если создаётся стикерпак масок. Устарело, начиная с Bot " "API 6.2, используйте sticker_type." -#: of telebot.TeleBot.create_new_sticker_set:36 +#: of telebot.TeleBot.create_new_sticker_set:39 +#, fuzzy msgid "" -"Optional, Type of stickers in the set, pass “regular” or “mask”. Custom " -"emoji sticker sets can't be created via the Bot API at the moment. By " -"default, a regular sticker set is created." +"Type of stickers in the set, pass “regular”, “mask”, or “custom_emoji”. " +"By default, a regular sticker set is created." msgstr "" "Необязательный, тип стикерпака, передайте “regular” или “mask”. " "Стикерпаки кастомных эмодзи пока что не могут быть созданы с помощью Bot " "API. По умолчанию будет создан обычный стикерпак." +#: of telebot.TeleBot.create_new_sticker_set:45 +msgid "" +"Pass True if stickers in the sticker set must be repainted to the color " +"of text when used in messages, the accent color if used as emoji status, " +"white on chat photos, or another appropriate color based on context; for " +"custom emoji sticker sets only" +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:50 +msgid "List of stickers to be added to the set" +msgstr "" + +#: of telebot.TeleBot.create_new_sticker_set:53 +msgid "" +"Format of stickers in the set, must be one of “static”, “animated”, " +"“video”" +msgstr "" + #: of telebot.TeleBot.decline_chat_join_request:1 msgid "" "Use this method to decline a chat join request. The bot must be an " @@ -1921,6 +1996,13 @@ msgstr "" msgid "File identifier of the sticker" msgstr "id файла стикера" +#: of telebot.TeleBot.delete_sticker_set:1 +#, fuzzy +msgid "Use this method to delete a sticker set. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы удалить стикер из стикерпака, созданного " +"ботом. Возвращает True в случае успеха." + #: of telebot.TeleBot.delete_webhook:1 msgid "" "Use this method to remove webhook integration if you decide to switch " @@ -2038,8 +2120,8 @@ msgid "" "Optional, New name of the topic, 1-128 characters. If not specififed or " "empty, the current name of the topic will be kept" msgstr "" -"Необязательный, новое имя топика, 1-128 символов. Если не задано или пустое, " -"сохранится текущее имя топика" +"Необязательный, новое имя топика, 1-128 символов. Если не задано или " +"пустое, сохранится текущее имя топика" #: of telebot.TeleBot.edit_forum_topic:17 msgid "" @@ -2054,7 +2136,6 @@ msgstr "" "чтобы убрать иконку. Если не задан, сохранится текущая иконка топика" #: of telebot.TeleBot.edit_general_forum_topic:1 - msgid "" "Use this method to edit the name of the 'General' topic in a forum " "supergroup chat. The bot must be an administrator in the chat for this to" @@ -2067,14 +2148,12 @@ msgstr "" "True в случае успеха." #: of telebot.TeleBot.edit_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#editgeneralforumtopic" msgstr "Документация Telegram: https://core.telegram.org/bots/api#editforumtopic" #: of telebot.TeleBot.edit_general_forum_topic:10 - msgid "New topic name, 1-128 characters" msgstr "Название товара, 1-32 символа" @@ -2139,8 +2218,8 @@ msgid "" "On success, if edited message is sent by the bot, the edited Message is " "returned, otherwise True is returned." msgstr "" -"В случае успеха если изменённое сообщение отправлено ботом, возвращается" -" новый объект Message, иначе (inline сообщения) возвращается True." +"В случае успеха если изменённое сообщение отправлено ботом, возвращается " +"новый объект Message, иначе (inline сообщения) возвращается True." #: of telebot.TeleBot.edit_message_caption:27 msgid ":obj:`types.Message` | :obj:`bool`" @@ -2160,9 +2239,9 @@ msgid "" "message is not an inline message, the edited Message is returned, " "otherwise True is returned." msgstr "" -"отключено вызовом метода stopMessageLiveLocation. В случае успеха если измененное " -"сообщение не является inline сообщением, возвращается новый объект Message, " -"иначе возвращается True." +"отключено вызовом метода stopMessageLiveLocation. В случае успеха если " +"измененное сообщение не является inline сообщением, возвращается новый " +"объект Message, иначе возвращается True." #: of telebot.TeleBot.edit_message_live_location:5 msgid "" @@ -2229,8 +2308,8 @@ msgid "" "On success, if the edited message is not an inline message, the edited " "Message is returned, otherwise True is returned." msgstr "" -"В случае успеха если измененное сообщение не является inline сообщением," -" возвращается новый объект Message, иначе возвращается True." +"В случае успеха если измененное сообщение не является inline сообщением, " +"возвращается новый объект Message, иначе возвращается True." #: of telebot.TeleBot.edit_message_live_location:39 #: telebot.TeleBot.stop_message_live_location:23 @@ -2270,8 +2349,8 @@ msgid "" " target chat or username of the target channel (in the format " "@channelusername)" msgstr "" -"Обязательный, если не указан inline_message_id. Уникальный id чата " -"или username канала (в формате @channelusername)" +"Обязательный, если не указан inline_message_id. Уникальный id чата или " +"username канала (в формате @channelusername)" #: of telebot.TeleBot.edit_message_media:13 #: telebot.TeleBot.edit_message_reply_markup:8 @@ -2280,8 +2359,7 @@ msgstr "" msgid "" "Required if inline_message_id is not specified. Identifier of the sent " "message" -msgstr "" -"Обязательный, если не указан inline_message_id. id отправленного сообщения" +msgstr "Обязательный, если не указан inline_message_id. id отправленного сообщения" #: of telebot.TeleBot.edit_message_media:23 #: telebot.TeleBot.edit_message_reply_markup:18 @@ -2322,8 +2400,8 @@ msgid "" "List of special entities that appear in the message text, which can be " "specified instead of parse_mode" msgstr "" -"Список отформатированных частей в тексте сообщения, " -"можно использовать вместо parse_mode" +"Список отформатированных частей в тексте сообщения, можно использовать " +"вместо parse_mode" #: of telebot.TeleBot.edit_message_text:23 telebot.TeleBot.send_message:21 msgid "Disables link previews for links in this message" @@ -2335,8 +2413,8 @@ msgid "" "edited. As a parameter to the decorator function, it passes " ":class:`telebot.types.Message` object." msgstr "" -"Обрабатывает новую версию поста в канале, который доступен боту и был изменён. " -"В качестве параметра, передаёт в декорируемую функцию объект " +"Обрабатывает новую версию поста в канале, который доступен боту и был " +"изменён. В качестве параметра, передаёт в декорируемую функцию объект " ":class:`telebot.types.Message`." #: of telebot.TeleBot.edited_message_handler:1 @@ -2345,8 +2423,8 @@ msgid "" " As a parameter to the decorator function, it passes " ":class:`telebot.types.Message` object." msgstr "" -"Обрабатывает новую версию сообщения, которое доступно боту и было изменено. " -"В качестве параметра, передаёт в декорируемую функцию объект " +"Обрабатывает новую версию сообщения, которое доступно боту и было " +"изменено. В качестве параметра, передаёт в декорируемую функцию объект " ":class:`telebot.types.Message`." #: of telebot.TeleBot.edited_message_handler:16 @@ -2356,7 +2434,9 @@ msgstr "список видов чатов" #: of telebot.TeleBot.enable_save_next_step_handlers:1 msgid "Enable saving next step handlers (by default saving disabled)" -msgstr "Разрешить сохранение next step хендлеров (по умолчанию сохранение отключено)" +msgstr "" +"Разрешить сохранение next step хендлеров (по умолчанию сохранение " +"отключено)" #: of telebot.TeleBot.enable_save_next_step_handlers:3 #: telebot.TeleBot.enable_save_reply_handlers:3 @@ -2366,9 +2446,10 @@ msgid "" "saving capability for handlers. And the same implementation is now " "available with FileHandlerBackend" msgstr "" -"Эта функция, целью которой было включить возможность сохранения файлов для обработчиков, " -"явно назначает FileHandlerBackend (вместо Saver) просто для сохранения обратной совместимости. " -"Та же реализация теперь доступна с FileHandlerBackend." +"Эта функция, целью которой было включить возможность сохранения файлов " +"для обработчиков, явно назначает FileHandlerBackend (вместо Saver) просто" +" для сохранения обратной совместимости. Та же реализация теперь доступна " +"с FileHandlerBackend." #: of telebot.TeleBot.enable_save_next_step_handlers:7 #: telebot.TeleBot.enable_save_reply_handlers:7 @@ -2396,8 +2477,9 @@ msgid "" "It is recommended to pass a :class:`~telebot.storage.StatePickleStorage` " "instance as state_storage to TeleBot class." msgstr "" -"Рекомендуется передавать экземпляр класса :class:`~telebot.storage.StatePickleStorage` " -"в качестве state_storage при инициализации класса TeleBot вместо использования этой функции." +"Рекомендуется передавать экземпляр класса " +":class:`~telebot.storage.StatePickleStorage` в качестве state_storage при" +" инициализации класса TeleBot вместо использования этой функции." #: of telebot.TeleBot.enable_saving_states:7 msgid "Filename of saving file, defaults to \"./.state-save/states.pkl\"" @@ -2409,9 +2491,9 @@ msgid "" "The bot must be an administrator in the chat for this to work and must " "have the appropriate admin rights." msgstr "" -"Используйте этот метод, чтобы создать или заменить главную ссылку-приглашение " -"в супергруппу или канал, созданную ботом. Бот должен быть администратором чата " -"и иметь соответствующие права администратора." +"Используйте этот метод, чтобы создать или заменить главную " +"ссылку-приглашение в супергруппу или канал, созданную ботом. Бот должен " +"быть администратором чата и иметь соответствующие права администратора." #: of telebot.TeleBot.export_chat_invite_link:4 msgid "" @@ -2451,9 +2533,10 @@ msgid "" "name of the user for one-on-one conversations, current username of a " "user, group or channel, etc.). Returns a Chat object on success." msgstr "" -"Используйте этот метод, чтобы получить актуальную информацию о чате (текущее " -"имя пользователя для персональных диалогов, текущий username пользователя, " -"группы или канала и т.д.). В случае успеха возвращает объект Chat." +"Используйте этот метод, чтобы получить актуальную информацию о чате " +"(текущее имя пользователя для персональных диалогов, текущий username " +"пользователя, группы или канала и т.д.). В случае успеха возвращает " +"объект Chat." #: of telebot.TeleBot.get_chat:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#getchat" @@ -2465,8 +2548,8 @@ msgid "" "Unique identifier for the target chat or username of the target " "supergroup or channel (in the format @channelusername)" msgstr "" -"Уникальный id чата или username супергруппы или канала " -"(в формате @channelusername)" +"Уникальный id чата или username супергруппы или канала (в формате " +"@channelusername)" #: of telebot.TeleBot.get_chat:9 msgid "Chat information" @@ -2482,9 +2565,9 @@ msgid "" "returns an Array of ChatMember objects that contains information about " "all chat administrators except other bots." msgstr "" -"Используйте этот метод, чтобы получить список администраторов чата. " -"В случае успеха возвращает массив объектов ChatMember, содержащих информацию " -"обо всех администраторах чата, кроме других ботов." +"Используйте этот метод, чтобы получить список администраторов чата. В " +"случае успеха возвращает массив объектов ChatMember, содержащих " +"информацию обо всех администраторах чата, кроме других ботов." #: of telebot.TeleBot.get_chat_administrators:5 msgid "" @@ -2507,8 +2590,8 @@ msgid "" "Use this method to get information about a member of a chat. Returns a " "ChatMember object on success." msgstr "" -"Используйте этот метод, чтобы получить информацию об участнике чата. Возвращает " -"объект ChatMember в случае успеха." +"Используйте этот метод, чтобы получить информацию об участнике чата. " +"Возвращает объект ChatMember в случае успеха." #: of telebot.TeleBot.get_chat_member:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#getchatmember" @@ -2539,6 +2622,9 @@ msgid "Number of members in the chat." msgstr "Количество участников чата." #: of telebot.TeleBot.get_chat_member_count:9 +#: telebot.TeleBot.send_video_note:14 telebot.TeleBot.send_video_note:17 +#: telebot.TeleBot.send_video_note:20 telebot.TeleBot.send_video_note:31 +#: telebot.TeleBot.send_video_note:46 msgid ":obj:`int`" msgstr "" @@ -2548,7 +2634,8 @@ msgid "" "private chat, or the default menu button. Returns MenuButton on success." msgstr "" "Используйте этот метод, чтобы получить текущее значение кнопки menu в " -"приватном чате, или кнопку menu по умолчанию. Возвращает MenuButton в случае успеха." +"приватном чате, или кнопку menu по умолчанию. Возвращает MenuButton в " +"случае успеха." #: of telebot.TeleBot.get_chat_menu_button:5 msgid "" @@ -2563,8 +2650,8 @@ msgid "" "Unique identifier for the target private chat. If not specified, default " "bot's menu button will be returned." msgstr "" -"Уникальный id приватного чата. Если не указан, будет возвращена " -"кнопка menu по умолчанию." +"Уникальный id приватного чата. Если не указан, будет возвращена кнопка " +"menu по умолчанию." #: of telebot.TeleBot.get_chat_menu_button:11 msgid "types.MenuButton" @@ -2579,15 +2666,14 @@ msgid "" "Use this method to get information about custom emoji stickers by their " "identifiers. Returns an Array of Sticker objects." msgstr "" -"Используйте этот метод, чтобы получить информацию о кастомных эмодзи по их " -"id. Возвращает массив объектов Sticker." +"Используйте этот метод, чтобы получить информацию о кастомных эмодзи по " +"их id. Возвращает массив объектов Sticker." #: of telebot.TeleBot.get_custom_emoji_stickers:4 msgid "" "List of custom emoji identifiers. At most 200 custom emoji identifiers " "can be specified." -msgstr "" -"Список id кастомных эмодзи. Можно указать не более 200 id." +msgstr "Список id кастомных эмодзи. Можно указать не более 200 id." #: of telebot.TeleBot.get_custom_emoji_stickers:7 msgid "Returns an Array of Sticker objects." @@ -2605,11 +2691,12 @@ msgid "" "link will be valid for at least 1 hour. When the link expires, a new one " "can be requested by calling get_file again." msgstr "" -"Используйте этот метод, чтобы получить базовую информацию о файле и подготовить " -"его к скачиванию. На текущий момент, боты могут скачивать файлы весом до 20MB. " -"В случае успеха возвращается объект File. Гарантируется, что ссылка на скачивание " -"будет актуальна как минимум 1 час. Когда ссылка перестаёт быть актуальной, новая " -"может быть снова запрошена с помощью get_file." +"Используйте этот метод, чтобы получить базовую информацию о файле и " +"подготовить его к скачиванию. На текущий момент, боты могут скачивать " +"файлы весом до 20MB. В случае успеха возвращается объект File. " +"Гарантируется, что ссылка на скачивание будет актуальна как минимум 1 " +"час. Когда ссылка перестаёт быть актуальной, новая может быть снова " +"запрошена с помощью get_file." #: of telebot.TeleBot.get_file:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#getfile" @@ -2619,7 +2706,7 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#ge msgid "File identifier" msgstr "id файла" -#: of telebot.TeleBot.get_file:12 telebot.TeleBot.upload_sticker_file:14 +#: of telebot.TeleBot.get_file:12 telebot.TeleBot.upload_sticker_file:21 msgid ":class:`telebot.types.File`" msgstr "" @@ -2641,9 +2728,9 @@ msgid "" "forum topic icon by any user. Requires no parameters. Returns an Array of" " Sticker objects." msgstr "" -"Используйте этот метод, чтобы получить кастомные эмодзи, которые могут быть " -"использованы любыми пользователями в качестве иконок топиков. Не требует параметров. " -"Возвращает массив объектов Sticker." +"Используйте этот метод, чтобы получить кастомные эмодзи, которые могут " +"быть использованы любыми пользователями в качестве иконок топиков. Не " +"требует параметров. Возвращает массив объектов Sticker." #: of telebot.TeleBot.get_forum_topic_icon_stickers:4 msgid "" @@ -2667,9 +2754,9 @@ msgid "" "of the specified user and several of their neighbors in a game. On " "success, returns an Array of GameHighScore objects." msgstr "" -"Используйте этот метод, чтобы получить данные для таблицы рекордов. Вернёт " -"очки указанного пользователя и несколько соседних результатов. В случае успеха " -"возвращает массив объектов GameHighScore." +"Используйте этот метод, чтобы получить данные для таблицы рекордов. " +"Вернёт очки указанного пользователя и несколько соседних результатов. В " +"случае успеха возвращает массив объектов GameHighScore." #: of telebot.TeleBot.get_game_high_scores:4 msgid "" @@ -2678,10 +2765,10 @@ msgid "" "users if the user and their neighbors are not among them. Please note " "that this behavior is subject to change." msgstr "" -"На текущий момент этот метод вернёт очки указанного пользователя и по два соседних " -"результата с каждой стороны. Также вернет результаты трёх лучших игроков, если " -"результат пользователя и соседние не являются тремя лучшими. Пожалуйста учитывайте, " -"что это поведение может быть изменено." +"На текущий момент этот метод вернёт очки указанного пользователя и по два" +" соседних результата с каждой стороны. Также вернет результаты трёх " +"лучших игроков, если результат пользователя и соседние не являются тремя " +"лучшими. Пожалуйста учитывайте, что это поведение может быть изменено." #: of telebot.TeleBot.get_game_high_scores:8 msgid "" @@ -2692,7 +2779,7 @@ msgstr "" "https://core.telegram.org/bots/api#getgamehighscores" #: of telebot.TeleBot.get_game_high_scores:10 telebot.TeleBot.retrieve_data:3 -#: telebot.TeleBot.set_game_score:5 telebot.TeleBot.set_sticker_set_thumb:9 +#: telebot.TeleBot.set_game_score:5 telebot.TeleBot.set_sticker_set_thumbnail:9 msgid "User identifier" msgstr "id пользователя" @@ -2718,8 +2805,8 @@ msgid "" "Use this method to get the current list of the bot's commands. Returns " "List of BotCommand on success." msgstr "" -"Используйте этот метод, чтобы получить текущий список команд бота. Возвращает " -"список объектов BotCommand в случае успеха." +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." #: of telebot.TeleBot.get_my_commands:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#getmycommands" @@ -2738,8 +2825,9 @@ msgid "" "Use this method to get the current default administrator rights of the " "bot. Returns ChatAdministratorRights on success." msgstr "" -"Используйте этот метод, чтобы получить текущие права администратора для бота по умолчанию. " -"Возвращает объект ChatAdministratorRights в случае успеха." +"Используйте этот метод, чтобы получить текущие права администратора для " +"бота по умолчанию. Возвращает объект ChatAdministratorRights в случае " +"успеха." #: of telebot.TeleBot.get_my_default_administrator_rights:4 msgid "" @@ -2755,9 +2843,9 @@ msgid "" " Otherwise, the default administrator rights of the bot for groups and " "supergroups will be returned." msgstr "" -"Передайте True, чтобы получить права администратора для бота по умолчанию в каналах. " -"Иначе, будут возвращены права администратора для бота по умолчанию в группах и " -"супергруппах." +"Передайте True, чтобы получить права администратора для бота по умолчанию" +" в каналах. Иначе, будут возвращены права администратора для бота по " +"умолчанию в группах и супергруппах." #: of telebot.TeleBot.get_my_default_administrator_rights:9 msgid "Returns ChatAdministratorRights on success." @@ -2767,6 +2855,79 @@ msgstr "Возвращает объект ChatAdministratorRights в случа msgid ":class:`telebot.types.ChatAdministratorRights`" msgstr "" +#: of telebot.TeleBot.get_my_description:1 +#, fuzzy +msgid "" +"Use this method to get the current bot description for the given user " +"language. Returns BotDescription on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.TeleBot.get_my_description:4 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getmydescription" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#setchatdescription" + +#: of telebot.TeleBot.get_my_description:6 +#: telebot.TeleBot.get_my_short_description:6 +msgid "A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.TeleBot.get_my_description:9 +#, fuzzy +msgid ":class:`telebot.types.BotDescription`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + +#: of telebot.TeleBot.get_my_name:1 +#, fuzzy +msgid "" +"Use this method to get the current bot name for the given user language. " +"Returns BotName on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.TeleBot.get_my_name:4 +#, fuzzy +msgid "Telegram documentation: https://core.telegram.org/bots/api#getmyname" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#getme" + +#: of telebot.TeleBot.get_my_name:6 +msgid "Optional. A two-letter ISO 639-1 language code or an empty string" +msgstr "" + +#: of telebot.TeleBot.get_my_name:9 +#, fuzzy +msgid ":class:`telebot.types.BotName`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + +#: of telebot.TeleBot.get_my_short_description:1 +#, fuzzy +msgid "" +"Use this method to get the current bot short description for the given " +"user language. Returns BotShortDescription on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.TeleBot.get_my_short_description:4 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getmyshortdescription" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#setchatdescription" + +#: of telebot.TeleBot.get_my_short_description:9 +msgid ":class:`telebot.types.BotShortDescription`" +msgstr "" + #: of telebot.TeleBot.get_state:1 msgid "" "Gets current state of a user. Not recommended to use this method. But it " @@ -2788,8 +2949,8 @@ msgid "" "Use this method to get a sticker set. On success, a StickerSet object is " "returned." msgstr "" -"Используйте этот метод, чтобы получить стикерпак. В случае успеха возвращается " -"объект StickerSet." +"Используйте этот метод, чтобы получить стикерпак. В случае успеха " +"возвращается объект StickerSet." #: of telebot.TeleBot.get_sticker_set:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#getstickerset" @@ -2808,8 +2969,8 @@ msgid "" "Use this method to receive incoming updates using long polling (wiki). An" " Array of Update objects is returned." msgstr "" -"Используйте этот метод, чтобы получить новые апдейты с помощью long polling-а (wiki). " -"Возвращается массив объектов Update." +"Используйте этот метод, чтобы получить новые апдейты с помощью long " +"polling-а (wiki). Возвращается массив объектов Update." #: of telebot.TeleBot.get_updates:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#getupdates" @@ -2828,17 +2989,17 @@ msgstr "" "id первого апдейта. Должен быть на единицу больше наибольшего id среди " "ранее полученных апдейтов. По умолчанию, возвращается список апдейтов, " "начиная с самого раннего неполученного. Апдейт считается полученным как " -"только вызван метод getUpdates со смещением больше, чем id этого апдейта. " -"Отрицательное смещение может быть указано для получения последних offset апдейтов. " -"Все предыдущие апдейты будут считаться полученными." +"только вызван метод getUpdates со смещением больше, чем id этого апдейта." +" Отрицательное смещение может быть указано для получения последних offset" +" апдейтов. Все предыдущие апдейты будут считаться полученными." #: of telebot.TeleBot.get_updates:12 msgid "" "Limits the number of updates to be retrieved. Values between 1-100 are " "accepted. Defaults to 100." msgstr "" -"Максимальное число апдейтов для получения. Допускаются значения от 1 до 100. " -"По умолчанию 100." +"Максимальное число апдейтов для получения. Допускаются значения от 1 до " +"100. По умолчанию 100." #: of telebot.TeleBot.get_updates:15 telebot.TeleBot.get_webhook_info:6 #: telebot.TeleBot.polling:21 @@ -2909,9 +3070,9 @@ msgid "" " success, returns a WebhookInfo object. If the bot is using getUpdates, " "will return an object with the url field empty." msgstr "" -"Используйте этот метод, чтобы получить текущий статус вебхука. Не требует параметров. " -"В случае успеха возвращает объект WebhookInfo. Если бот использует getUpdates, " -"вернёт объект с пустым атрибутом url." +"Используйте этот метод, чтобы получить текущий статус вебхука. Не требует" +" параметров. В случае успеха возвращает объект WebhookInfo. Если бот " +"использует getUpdates, вернёт объект с пустым атрибутом url." #: of telebot.TeleBot.get_webhook_info:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#getwebhookinfo" @@ -2926,7 +3087,6 @@ msgid ":class:`telebot.types.WebhookInfo`" msgstr "" #: of telebot.TeleBot.hide_general_forum_topic:1 - msgid "" "Use this method to hide the 'General' topic in a forum supergroup chat. " "The bot must be an administrator in the chat for this to work and must " @@ -2938,7 +3098,6 @@ msgstr "" "True в случае успеха." #: of telebot.TeleBot.hide_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#hidegeneralforumtopic" @@ -2949,8 +3108,8 @@ msgid "" "Wrap polling with infinite loop and exception handling to avoid bot stops" " polling." msgstr "" -"Запустить поллинг в бесконечном цикле с обработкой исключений, чтобы избежать " -"непредвиденных остановок поллинга." +"Запустить поллинг в бесконечном цикле с обработкой исключений, чтобы " +"избежать непредвиденных остановок поллинга." #: of telebot.TeleBot.infinity_polling:5 telebot.TeleBot.polling:13 msgid "Install watchdog and psutil before using restart_on_change option." @@ -2974,8 +3133,9 @@ msgid "" "logging. Use logger levels from logging as a value. None/NOTSET = no " "error logging" msgstr "" -"Кастомный (отличающийся от логгера) уровень логирования для infinity_polling. " -"Используйте уровни из logging в качестве значений. None/NOTSET = не логировать ошибки." +"Кастомный (отличающийся от логгера) уровень логирования для " +"infinity_polling. Используйте уровни из logging в качестве значений. " +"None/NOTSET = не логировать ошибки." #: of telebot.TeleBot.infinity_polling:20 msgid "" @@ -2994,8 +3154,8 @@ msgstr "" "util.update_types. Укажите пустой список, чтобы получать все апдейты, " "кроме chat_member (по умолчанию). Если не задан, будет использована " "последняя настройка. Пожалуйста учитывайте, что этот параметр не влияет " -"на апдейты, отправленные до вызова get_updates, поэтому нежелательные апдейты " -"могут быть получены в течение короткого периода времени." +"на апдейты, отправленные до вызова get_updates, поэтому нежелательные " +"апдейты могут быть получены в течение короткого периода времени." #: of telebot.TeleBot.infinity_polling:29 telebot.TeleBot.polling:47 msgid "Restart a file on file(s) change. Defaults to False" @@ -3037,8 +3197,9 @@ msgid "" "FileHandlerBackend before entering this function" msgstr "" "Эта функция оставлена для обратной совместимости, для загрузки хендлеров " -"из файла с помощью FileHandlerBackend и рекомендуется к использованию только " -"если next_step_backend был определён как FileHandlerBackend до вызова этой функции" +"из файла с помощью FileHandlerBackend и рекомендуется к использованию " +"только если next_step_backend был определён как FileHandlerBackend до " +"вызова этой функции" #: of telebot.TeleBot.load_next_step_handlers:8 msgid "" @@ -3052,8 +3213,7 @@ msgstr "" msgid "" "If True is passed, after the loading file will be deleted, defaults to " "True" -msgstr "" -"Если передано True, файл будет удалён после загрузки, по умолчанию True" +msgstr "Если передано True, файл будет удалён после загрузки, по умолчанию True" #: of telebot.TeleBot.load_reply_handlers:1 msgid "Load reply handlers from save file" @@ -3067,8 +3227,9 @@ msgid "" "before entering this function" msgstr "" "Эта функция оставлена для обратной совместимости, для загрузки хендлеров " -"из файла с помощью FileHandlerBackend и рекомендуется к использованию только " -"если reply_backend был определён как FileHandlerBackend до вызова этой функции" +"из файла с помощью FileHandlerBackend и рекомендуется к использованию " +"только если reply_backend был определён как FileHandlerBackend до вызова " +"этой функции" #: of telebot.TeleBot.load_reply_handlers:7 msgid "" @@ -3082,8 +3243,7 @@ msgstr "" msgid "" "If True is passed, after the loading file will be deleted, defaults to " "True, defaults to True" -msgstr "" -"Если передано True, файл будет удалён после загрузки, по умолчанию True" +msgstr "Если передано True, файл будет удалён после загрузки, по умолчанию True" #: of telebot.TeleBot.log_out:1 msgid "" @@ -3096,10 +3256,10 @@ msgid "" msgstr "" "Используйте этот метод, чтобы отключиться от облачного Bot API сервера " "перед локальным запуском бота. Вы ДОЛЖНЫ отключить бота перед тем, как " -"запускать его локально, иначе нет никаких гарантий, что бот будет получать " -"апдейты. После успешного вызова, вы можете тут же подключиться к локальному " -"серверу, но не сможете подключиться обратно к облачному Bot API серверу в " -"течение 10 минут. Возвращает True в случае успеха." +"запускать его локально, иначе нет никаких гарантий, что бот будет " +"получать апдейты. После успешного вызова, вы можете тут же подключиться к" +" локальному серверу, но не сможете подключиться обратно к облачному Bot " +"API серверу в течение 10 минут. Возвращает True в случае успеха." #: of telebot.TeleBot.log_out:8 msgid "Telegram documentation: https://core.telegram.org/bots/api#logout" @@ -3112,8 +3272,8 @@ msgid "" ":class:`telebot.types.Message` object. All message handlers are tested in" " the order they were added." msgstr "" -"Обрабатывает входящие сообщения всех видов - text, photo, sticker, и т.д. " -"В качестве параметра передаёт в декорируемую функцию объект " +"Обрабатывает входящие сообщения всех видов - text, photo, sticker, и т.д." +" В качестве параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.Message`. Все хендлеры сообщений проверяются в том " "порядке, в котором были добавлены." @@ -3132,9 +3292,9 @@ msgid "" "first parameter. It must return True if the command should handle the " "message." msgstr "" -"Необязательная lambda функция. Получает сообщение (объект Message) в качестве " -"первого параметра. Функция должна вернуть True если хендлер должен обработать " -"сообщение." +"Необязательная lambda функция. Получает сообщение (объект Message) в " +"качестве первого параметра. Функция должна вернуть True если хендлер " +"должен обработать сообщение." #: of telebot.TeleBot.message_handler:52 #: telebot.TeleBot.register_edited_channel_post_handler:23 @@ -3154,10 +3314,10 @@ msgid "" "and check type of the update inside the handler if more than one " "update_type is given" msgstr "" -"Этот декоратор может быть использован, чтобы декорировать функции, которые " -"будут использоваться в качестве middleware перед обработкой апдейтов, " -"будьте аккуратны и проверяйте вид апдейта внутри функции если возможны апдейты " -"разных видов" +"Этот декоратор может быть использован, чтобы декорировать функции, " +"которые будут использоваться в качестве middleware перед обработкой " +"апдейтов, будьте аккуратны и проверяйте вид апдейта внутри функции если " +"возможны апдейты разных видов" #: of telebot.TeleBot.middleware_handler:9 msgid "Usage of middleware_handler" @@ -3194,9 +3354,9 @@ msgid "" "administrator in the chat for this to work and must have the appropriate " "admin rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы закрепить сообщение в супергруппе. Бот должен " -"быть администратором чата и иметь соответствующие права администратора. " -"Возвращает True в случае успеха." +"Используйте этот метод, чтобы закрепить сообщение в супергруппе. Бот " +"должен быть администратором чата и иметь соответствующие права " +"администратора. Возвращает True в случае успеха." #: of telebot.TeleBot.pin_chat_message:5 msgid "Telegram documentation: https://core.telegram.org/bots/api#pinchatmessage" @@ -3211,8 +3371,8 @@ msgid "" "Pass True, if it is not necessary to send a notification to all group " "members about the new pinned message" msgstr "" -"Передайте True, если всем участникам группы необходимо отправить уведомление " -"о закреплённом сообщении" +"Передайте True, если всем участникам группы необходимо отправить " +"уведомление о закреплённом сообщении" #: of telebot.TeleBot.poll_answer_handler:1 msgid "" @@ -3223,8 +3383,8 @@ msgid "" msgstr "" "Обрабатывает изменения ответа пользователя в не анонимном опросе(когда " "пользователь меняет выбор). Боты получают новые ответы только в опросах, " -"которые отправили сами. В качестве параметра передаёт в декорируемую функцию " -"объект :class:`telebot.types.PollAnswer`." +"которые отправили сами. В качестве параметра передаёт в декорируемую " +"функцию объект :class:`telebot.types.PollAnswer`." #: of telebot.TeleBot.poll_handler:1 msgid "" @@ -3232,9 +3392,10 @@ msgid "" "polls and polls, which are sent by the bot As a parameter to the " "decorator function, it passes :class:`telebot.types.Poll` object." msgstr "" -"Обрабатывает изменения в состоянии опроса. Боты получают только апдейты " -"о завершенных опросах и опросах, которые отправили сами. В качестве " -"параметра передаёт в декорируемую функцию объект :class:`telebot.types.Poll`." +"Обрабатывает изменения в состоянии опроса. Боты получают только апдейты о" +" завершенных опросах и опросах, которые отправили сами. В качестве " +"параметра передаёт в декорируемую функцию объект " +":class:`telebot.types.Poll`." #: of telebot.TeleBot.polling:1 msgid "" @@ -3283,8 +3444,8 @@ msgstr "" "util.update_types. Укажите пустой список, чтобы получать все апдейты, " "кроме chat_member (по умолчанию). Если не задан, будет использована " "последняя настройка. Пожалуйста учитывайте, что этот параметр не влияет " -"на апдейты, отправленные до вызова get_updates, поэтому нежелательные апдейты " -"могут быть получены в течение короткого периода времени." +"на апдейты, отправленные до вызова get_updates, поэтому нежелательные " +"апдейты могут быть получены в течение короткого периода времени." #: of telebot.TeleBot.polling:34 msgid "" @@ -3308,15 +3469,15 @@ msgid "" " call to the get_updates, so unwanted updates may be received for a short" " period of time." msgstr "" -"Пожалуйста учитывайте, что этот параметр не влияет " -"на апдейты, отправленные до вызова get_updates, поэтому нежелательные апдейты " -"могут быть получены в течение короткого периода времени." +"Пожалуйста учитывайте, что этот параметр не влияет на апдейты, " +"отправленные до вызова get_updates, поэтому нежелательные апдейты могут " +"быть получены в течение короткого периода времени." #: of telebot.TeleBot.polling:44 msgid "Deprecated, use non_stop. Old typo, kept for backward compatibility." msgstr "" -"Устарело, используйте non_stop. " -"Старая опечатка, оставлено для обратной совместимости" +"Устарело, используйте non_stop. Старая опечатка, оставлено для обратной " +"совместимости" #: of telebot.TeleBot.polling:50 msgid "Path to watch for changes. Defaults to None" @@ -3328,8 +3489,8 @@ msgid "" "checkout. As a parameter to the decorator function, it passes " ":class:`telebot.types.PreCheckoutQuery` object." msgstr "" -"Новая pre-checkout query. Содержит полную информацию о заказе. " -"В качестве параметра передаёт в декорируемую функцию объект " +"Новая pre-checkout query. Содержит полную информацию о заказе. В качестве" +" параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.PreCheckoutQuery`." #: of telebot.TeleBot.process_new_updates:1 @@ -3337,8 +3498,8 @@ msgid "" "Processes new updates. Just pass list of subclasses of Update to this " "method." msgstr "" -"Обрабатывает новые апдейты. Просто передайте список апдейтов(Update и " -"его наследники)." +"Обрабатывает новые апдейты. Просто передайте список апдейтов(Update и его" +" наследники)." #: of telebot.TeleBot.process_new_updates:3 msgid "List of :class:`telebot.types.Update` objects." @@ -3355,9 +3516,10 @@ msgid "" "have the appropriate admin rights. Pass False for all boolean parameters " "to demote a user." msgstr "" -"Используйте этот метод, чтобы повысить или понизить пользователя в супергруппе " -"или канале. Бот должен быть администратором чата и иметь соответствующие права " -"администратора. Передайте False во все boolean параметры, чтобы понизить пользователя." +"Используйте этот метод, чтобы повысить или понизить пользователя в " +"супергруппе или канале. Бот должен быть администратором чата и иметь " +"соответствующие права администратора. Передайте False во все boolean " +"параметры, чтобы понизить пользователя." #: of telebot.TeleBot.promote_chat_member:5 msgid "" @@ -3371,44 +3533,53 @@ msgstr "" msgid "" "Unique identifier for the target chat or username of the target channel (" " in the format @channelusername)" -msgstr "" -"Уникальный id чата или username канала (в формате @channelusername)" +msgstr "Уникальный id чата или username канала (в формате @channelusername)" #: of telebot.TeleBot.promote_chat_member:14 msgid "" "Pass True, if the administrator can change chat title, photo and other " "settings" msgstr "" -"Передайте True, если администратор может менять название чата, аватарку " -"и другие настройки" +"Передайте True, если администратор может менять название чата, аватарку и" +" другие настройки" #: of telebot.TeleBot.promote_chat_member:17 msgid "Pass True, if the administrator can create channel posts, channels only" -msgstr "Передайте True, если администратор может создавать посты в канале, только для каналов" +msgstr "" +"Передайте True, если администратор может создавать посты в канале, только" +" для каналов" #: of telebot.TeleBot.promote_chat_member:20 msgid "" "Pass True, if the administrator can edit messages of other users, " "channels only" msgstr "" -"Передайте True, если администратор может изменять сообщения других пользователей, " -"только для каналов" +"Передайте True, если администратор может изменять сообщения других " +"пользователей, только для каналов" #: of telebot.TeleBot.promote_chat_member:23 msgid "Pass True, if the administrator can delete messages of other users" -msgstr "Передайте True, если администратор может удалять сообщения других пользователей" +msgstr "" +"Передайте True, если администратор может удалять сообщения других " +"пользователей" #: of telebot.TeleBot.promote_chat_member:26 msgid "Pass True, if the administrator can invite new users to the chat" -msgstr "Передайте True, если администратор может приглашать новых пользователей в чат" +msgstr "" +"Передайте True, если администратор может приглашать новых пользователей в" +" чат" #: of telebot.TeleBot.promote_chat_member:29 msgid "Pass True, if the administrator can restrict, ban or unban chat members" -msgstr "Передайте True, если администратор может ограничивать, банить или разбанивать участников чата" +msgstr "" +"Передайте True, если администратор может ограничивать, банить или " +"разбанивать участников чата" #: of telebot.TeleBot.promote_chat_member:32 msgid "Pass True, if the administrator can pin messages, supergroups only" -msgstr "Передайте True, если администратор может закреплять сообщения, только для супергрупп" +msgstr "" +"Передайте True, если администратор может закреплять сообщения, только для" +" супергрупп" #: of telebot.TeleBot.promote_chat_member:35 msgid "" @@ -3417,9 +3588,10 @@ msgid "" "directly or indirectly (promoted by administrators that were appointed by" " him)" msgstr "" -"Передайте True, если администратор может добавлять новых администраторов с " -"подмножеством его собственных прав администратора или понижать администраторов, " -"которых он повысил, напрямую или косвенно (администраторами, которых он назначил)" +"Передайте True, если администратор может добавлять новых администраторов " +"с подмножеством его собственных прав администратора или понижать " +"администраторов, которых он повысил, напрямую или косвенно " +"(администраторами, которых он назначил)" #: of telebot.TeleBot.promote_chat_member:40 msgid "Pass True, if the administrator's presence in the chat is hidden" @@ -3432,19 +3604,19 @@ msgid "" "anonymous administrators in supergroups and ignore slow mode. Implied by " "any other administrator privilege" msgstr "" -"Передайте True, если администратор имеет доступ к логу событий чата, статистике " -"чата, статистике сообщений в каналах, видеть участников канала, видеть анонимных " -"администраторов в супергруппах и игнорировать медленный режим. Подразумевается " -"любым другим правом администратора" +"Передайте True, если администратор имеет доступ к логу событий чата, " +"статистике чата, статистике сообщений в каналах, видеть участников " +"канала, видеть анонимных администраторов в супергруппах и игнорировать " +"медленный режим. Подразумевается любым другим правом администратора" #: of telebot.TeleBot.promote_chat_member:49 msgid "" "Pass True, if the administrator can manage voice chats For now, bots can " "use this privilege only for passing to other administrators." msgstr "" -"Передайте True, если администратор может управлять голосовыми чатами. На текущий " -"момент, боты могут использовать это право администратора только для передачи другим " -"администраторам." +"Передайте True, если администратор может управлять голосовыми чатами. На " +"текущий момент, боты могут использовать это право администратора только " +"для передачи другим администраторам." #: of telebot.TeleBot.promote_chat_member:53 msgid "Deprecated, use can_manage_video_chats." @@ -3455,8 +3627,8 @@ msgid "" "Pass True if the user is allowed to create, rename, close, and reopen " "forum topics, supergroups only" msgstr "" -"Передайте True, если пользователю разрешено создавать, переименовывать, закрывать, " -"и возобновлять топики, только для супергрупп" +"Передайте True, если пользователю разрешено создавать, переименовывать, " +"закрывать, и возобновлять топики, только для супергрупп" #: of telebot.TeleBot.register_callback_query_handler:1 msgid "Registers callback query handler." @@ -3497,8 +3669,8 @@ msgid "" "True if you need to pass TeleBot instance to handler(useful for " "separating handlers into different files)" msgstr "" -"True, если вам нужно передать экземпляр класса TeleBot в хендлер(удобно для " -"разбиения кода на файлы)" +"True, если вам нужно передать экземпляр класса TeleBot в хендлер(удобно " +"для разбиения кода на файлы)" #: of telebot.TeleBot.register_channel_post_handler:1 msgid "Registers channel post message handler." @@ -3551,7 +3723,8 @@ msgid "" "Registers a callback function to be notified when a reply to `message` " "arrives." msgstr "" -"Регистрирует функцию для вызова при получении ответа на выбранное сообщение." +"Регистрирует функцию для вызова при получении ответа на выбранное " +"сообщение." #: of telebot.TeleBot.register_for_reply:3 #: telebot.TeleBot.register_for_reply_by_message_id:3 @@ -3572,8 +3745,8 @@ msgid "" "The callback function to be called when a reply arrives. Must accept one " "`message` parameter, which will contain the replied message." msgstr "" -"Функция, которую нужно вызвать при получении ответа на сообщение. Должна принимать " -"параметр `message`, который будет содержать ответ на сообщение." +"Функция, которую нужно вызвать при получении ответа на сообщение. Должна " +"принимать параметр `message`, который будет содержать ответ на сообщение." #: of telebot.TeleBot.register_for_reply:12 #: telebot.TeleBot.register_for_reply_by_message_id:12 @@ -3638,7 +3811,8 @@ msgid "" "Registers a callback function to be notified when new message arrives " "after `message`." msgstr "" -"Регистрирует функцию для вызова при получении нового сообщения после указанного." +"Регистрирует функцию для вызова при получении нового сообщения после " +"указанного." #: of telebot.TeleBot.register_next_step_handler:3 #: telebot.TeleBot.register_next_step_handler_by_chat_id:3 @@ -3670,10 +3844,10 @@ msgid "" "Registers a callback function to be notified when new message arrives in " "the given chat." msgstr "" -"Регистрирует функцию для вызова при получении нового сообщения в заданном чате." +"Регистрирует функцию для вызова при получении нового сообщения в заданном" +" чате." #: of telebot.TeleBot.register_next_step_handler_by_chat_id:5 - msgid "The chat (chat ID) for which we want to handle new message." msgstr "Чат (id чата), в котором нужно обработать новое сообщение." @@ -3704,35 +3878,33 @@ msgid "" "the can_manage_topics administrator rights, unless it is the creator of " "the topic. Returns True on success." msgstr "" -"Используйте этот метод, чтобы возобновить закрытый топик в супергруппе с топиками. " -"Бот должен быть администратором чата и иметь права администратора can_manage_topics, " -"кроме случаев, когда бот является создателем топика. Возвращает True в случае успеха." +"Используйте этот метод, чтобы возобновить закрытый топик в супергруппе с " +"топиками. Бот должен быть администратором чата и иметь права " +"администратора can_manage_topics, кроме случаев, когда бот является " +"создателем топика. Возвращает True в случае успеха." #: of telebot.TeleBot.reopen_forum_topic:5 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#reopenforumtopic" -msgstr "" -"Документация Telegram: " -"https://core.telegram.org/bots/api#reopenforumtopic" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#reopenforumtopic" #: of telebot.TeleBot.reopen_forum_topic:10 msgid "Identifier of the topic to reopen" msgstr "id топика для возобновления" #: of telebot.TeleBot.reopen_general_forum_topic:1 - msgid "" "Use this method to reopen the 'General' topic in a forum supergroup chat." " The bot must be an administrator in the chat for this to work and must " "have can_manage_topics administrator rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы возобновить топик 'General' в супергруппе с топиками. " -"Бот должен быть администратором чата и иметь права администратора can_manage_topics, " -"кроме случаев, когда бот является создателем топика. Возвращает True в случае успеха." +"Используйте этот метод, чтобы возобновить топик 'General' в супергруппе с" +" топиками. Бот должен быть администратором чата и иметь права " +"администратора can_manage_topics, кроме случаев, когда бот является " +"создателем топика. Возвращает True в случае успеха." #: of telebot.TeleBot.reopen_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#reopengeneralforumtopic" @@ -3788,18 +3960,24 @@ msgstr "" "Документация Telegram: " "https://core.telegram.org/bots/api#restrictchatmember" -#: of telebot.TeleBot.restrict_chat_member:14 +#: of telebot.TeleBot.restrict_chat_member:8 +msgid "" +"Individual parameters are deprecated and will be removed, use " +"'permissions' instead." +msgstr "" + +#: of telebot.TeleBot.restrict_chat_member:17 msgid "" "Date when restrictions will be lifted for the user, unix time. If user is" " restricted for more than 366 days or less than 30 seconds from the " "current time, they are considered to be restricted forever" msgstr "" "Дата, когда ограничения будут сняты с пользователя, UNIX timestamp. Если " -"пользователь ограничен более чем на 366 дней или менее чем на 30 секунд с " -"текущего момента, он будет ограничен навсегда (пока ограничения не будут " -"сняты вручную)" +"пользователь ограничен более чем на 366 дней или менее чем на 30 секунд с" +" текущего момента, он будет ограничен навсегда (пока ограничения не будут" +" сняты вручную)" -#: of telebot.TeleBot.restrict_chat_member:19 +#: of telebot.TeleBot.restrict_chat_member:22 msgid "" "Pass True, if the user can send text messages, contacts, locations and " "venues" @@ -3807,62 +3985,78 @@ msgstr "" "Передайте True, если пользователь может отправлять текстовые сообщения, " "контакты, местоположения и места" -#: of telebot.TeleBot.restrict_chat_member:22 +#: of telebot.TeleBot.restrict_chat_member:25 msgid "" "Pass True, if the user can send audios, documents, photos, videos, video " "notes and voice notes, implies can_send_messages" msgstr "" -"Передайте True, если пользователь может отправлять аудио, документы, фото, " -"видео, видео заметки (кружочки) и голосовые сообщения, подразумевает " -"can_send_messages" +"Передайте True, если пользователь может отправлять аудио, документы, " +"фото, видео, видео заметки (кружочки) и голосовые сообщения, " +"подразумевает can_send_messages" -#: of telebot.TeleBot.restrict_chat_member:26 +#: of telebot.TeleBot.restrict_chat_member:29 msgid "Pass True, if the user is allowed to send polls, implies can_send_messages" msgstr "" -"Передайте True, если пользователю разрешено отправлять опросы, подразумевает " -"can_send_messages" +"Передайте True, если пользователю разрешено отправлять опросы, " +"подразумевает can_send_messages" -#: of telebot.TeleBot.restrict_chat_member:29 +#: of telebot.TeleBot.restrict_chat_member:32 msgid "" "Pass True, if the user can send animations, games, stickers and use " "inline bots, implies can_send_media_messages" msgstr "" -"Передайте True, если пользователь может отправлять гифки, игры, стикеры и " -"использовать inline ботов, подразумевает can_send_media_messages" +"Передайте True, если пользователь может отправлять гифки, игры, стикеры и" +" использовать inline ботов, подразумевает can_send_media_messages" -#: of telebot.TeleBot.restrict_chat_member:32 +#: of telebot.TeleBot.restrict_chat_member:35 msgid "" "Pass True, if the user may add web page previews to their messages, " "implies can_send_media_messages" msgstr "" -"Передайте True, если пользователь может добавлять превью ссылок к своим сообщениям, " -"подразумевает can_send_media_messages" +"Передайте True, если пользователь может добавлять превью ссылок к своим " +"сообщениям, подразумевает can_send_media_messages" -#: of telebot.TeleBot.restrict_chat_member:36 +#: of telebot.TeleBot.restrict_chat_member:39 msgid "" "Pass True, if the user is allowed to change the chat title, photo and " "other settings. Ignored in public supergroups" msgstr "" -"Передайте True, если пользователю разрешено изменять название чата, аватарку и " -"другие настройки. Игнорируется в публичных супергруппах" +"Передайте True, если пользователю разрешено изменять название чата, " +"аватарку и другие настройки. Игнорируется в публичных супергруппах" -#: of telebot.TeleBot.restrict_chat_member:40 +#: of telebot.TeleBot.restrict_chat_member:43 msgid "" "Pass True, if the user is allowed to invite new users to the chat, " "implies can_invite_users" -msgstr "" -"Передайте True, если пользователю разрешено приглашать пользователей в чат" +msgstr "Передайте True, если пользователю разрешено приглашать пользователей в чат" -#: of telebot.TeleBot.restrict_chat_member:44 +#: of telebot.TeleBot.restrict_chat_member:47 msgid "" "Pass True, if the user is allowed to pin messages. Ignored in public " "supergroups" msgstr "" -"Передайте True, если пользователю разрешено закреплять сообщения. Игнорируется " -"в публичных супергруппах" +"Передайте True, если пользователю разрешено закреплять сообщения. " +"Игнорируется в публичных супергруппах" -#: of telebot.TeleBot.restrict_chat_member:47 -#: telebot.TeleBot.set_chat_permissions:14 telebot.TeleBot.unban_chat_member:19 +#: of telebot.TeleBot.restrict_chat_member:50 +#: telebot.TeleBot.set_chat_permissions:14 +msgid "" +"Pass True if chat permissions are set independently. Otherwise, the " +"can_send_other_messages and can_add_web_page_previews permissions will " +"imply the can_send_messages, can_send_audios, can_send_documents, " +"can_send_photos, can_send_videos, can_send_video_notes, and " +"can_send_voice_notes permissions; the can_send_polls permission will " +"imply the can_send_messages permission." +msgstr "" + +#: of telebot.TeleBot.restrict_chat_member:56 +msgid "" +"Pass ChatPermissions object to set all permissions at once. Use this " +"param instead of passing all boolean parameters." +msgstr "" + +#: of telebot.TeleBot.restrict_chat_member:60 +#: telebot.TeleBot.set_chat_permissions:20 telebot.TeleBot.unban_chat_member:19 msgid "True on success" msgstr "True в случае успеха" @@ -3885,10 +4079,10 @@ msgid "" "must be an administrator in the chat for this to work and must have the " "appropriate admin rights." msgstr "" -"Используйте этот метод, чтобы аннулировать ссылку-приглашение, созданную ботом. " -"Примечание: Если аннулируется главная ссылка-приглашение, автоматически " -"генерируется новая. Бот должен быть администратором чата и иметь соответствующие " -"права администратора." +"Используйте этот метод, чтобы аннулировать ссылку-приглашение, созданную " +"ботом. Примечание: Если аннулируется главная ссылка-приглашение, " +"автоматически генерируется новая. Бот должен быть администратором чата и " +"иметь соответствующие права администратора." #: of telebot.TeleBot.revoke_chat_invite_link:5 msgid "" @@ -3941,10 +4135,11 @@ msgid "" " load on your bot's server, and higher values to increase your bot's " "throughput., defaults to None" msgstr "" -"Максимально-допустимое количество одновременных HTTPS подключений к вебхуку " -"для доставки апдейтов, 1-100. По умолчанию 40. Используйте меньшие значения, " -" чтобы уменьшить нагрузку на ваш сервер и большие значения для увеличения " -"пропускной способности вашего бота, по умолчанию None." +"Максимально-допустимое количество одновременных HTTPS подключений к " +"вебхуку для доставки апдейтов, 1-100. По умолчанию 40. Используйте " +"меньшие значения, чтобы уменьшить нагрузку на ваш сервер и большие " +"значения для увеличения пропускной способности вашего бота, по умолчанию " +"None." #: of telebot.TeleBot.run_webhooks:28 msgid "" @@ -3959,16 +4154,17 @@ msgstr "" "Например, укажите [“message”, “edited_channel_post”, “callback_query”], " "чтобы получать апдейты только этих видов. Полный список доступных видов " "апдейтов - util.update_types. Укажите пустой список, чтобы получать все " -"апдейты, кроме chat_member (по умолчанию). Если не задан, будет использована " -"последняя настройка. По умолчанию None" +"апдейты, кроме chat_member (по умолчанию). Если не задан, будет " +"использована последняя настройка. По умолчанию None" #: of telebot.TeleBot.run_webhooks:33 telebot.TeleBot.set_webhook:32 msgid "" "The fixed IP address which will be used to send webhook requests instead " "of the IP address resolved through DNS, defaults to None" msgstr "" -"Фиксированный IP адрес, который будет использоваться для отправки запросов " -"к вебхуку вместо IP адреса, полученного через DNS, по умолчанию None" +"Фиксированный IP адрес, который будет использоваться для отправки " +"запросов к вебхуку вместо IP адреса, полученного через DNS, по умолчанию " +"None" #: of telebot.TeleBot.run_webhooks:42 msgid "Secret token to be used to verify the webhook request, defaults to None" @@ -3993,10 +4189,10 @@ msgid "" "currently send animation files of up to 50 MB in size, this limit may be " "changed in the future." msgstr "" -"Используйте этот метод, чтобы отправить гифку (GIF или H.264/MPEG-4 AVC видео " -"без звука). В случае успеха возвращается отправленное сообщение (Message). На " -"текущий момент, боты могут отправлять гифки весом до 50 MB, это ограничение " -"может измениться в будущем." +"Используйте этот метод, чтобы отправить гифку (GIF или H.264/MPEG-4 AVC " +"видео без звука). В случае успеха возвращается отправленное сообщение " +"(Message). На текущий момент, боты могут отправлять гифки весом до 50 MB," +" это ограничение может измениться в будущем." #: of telebot.TeleBot.send_animation:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendanimation" @@ -4010,9 +4206,9 @@ msgid "" "new animation using multipart/form-data." msgstr "" "Гиф-ка для отправки. Передайте file_id (String), чтобы отправить гифку, " -"которая уже загружена на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить гифку из интернета или загрузите новую гифку " -"с помощью multipart/form-data." +"которая уже загружена на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить гифку из интернета или загрузите новую " +"гифку с помощью multipart/form-data." #: of telebot.TeleBot.send_animation:13 msgid "Duration of sent animation in seconds" @@ -4040,18 +4236,19 @@ msgstr "" "Обложка отправленного файла; может быть проигнорирована, если генерация " "обложки поддерживается на стороне сервера. Обложка должна быть картинкой " "в формате JPEG и весить менее 200 kB. Ширина и высота обложки не должны " -"превышать 320. Игнорируется, если файл не загружен с помощью multipart/form-" -"data. Обложки не могут быть использованы повторно и могут быть загружены " -"только как новый файл, так что вы можете передать “attach://” " -"если обложка была загружена с помощью multipart/form-data под именем ." +"превышать 320. Игнорируется, если файл не загружен с помощью multipart" +"/form-data. Обложки не могут быть использованы повторно и могут быть " +"загружены только как новый файл, так что вы можете передать " +"“attach://” если обложка была загружена с помощью " +"multipart/form-data под именем ." #: of telebot.TeleBot.send_animation:28 msgid "" "Animation caption (may also be used when resending animation by file_id)," " 0-1024 characters after entities parsing" msgstr "" -"Подпись к гифке (может быть использована при повторной отправке гифки по file_id), " -"0-1024 символа после форматирования" +"Подпись к гифке (может быть использована при повторной отправке гифки по " +"file_id), 0-1024 символа после форматирования" #: of telebot.TeleBot.send_animation:31 msgid "Mode for parsing entities in the animation caption" @@ -4070,10 +4267,15 @@ msgid "Identifier of a message thread, in which the video will be sent" msgstr "id топика, в который будет отправлено видео" #: of telebot.TeleBot.send_animation:60 - msgid "Pass True, if the animation should be sent as a spoiler" msgstr "Передайте True, если гифку нужно отправить как спойлер" +#: of telebot.TeleBot.send_animation:63 telebot.TeleBot.send_audio:63 +#: telebot.TeleBot.send_document:56 telebot.TeleBot.send_video:64 +#: telebot.TeleBot.send_video_note:48 +msgid "Deprecated. Use thumbnail instead" +msgstr "" + #: of telebot.TeleBot.send_audio:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -4082,11 +4284,12 @@ msgid "" " audio files of up to 50 MB in size, this limit may be changed in the " "future." msgstr "" -"Используйте этот метод, чтобы отправить аудио, если вы хотите, чтобы клиенты " -"(приложения) Telegram проигрывали их в музыкальном проигрывателе. Ваше аудио " -"должно быть в формате .MP3 или .M4A. В случае успеха возвращается отправленное " -"сообщение (Message). На текущий момент, боты могут отправлять аудио весом до 50 MB, " -"это ограничение может измениться в будущем." +"Используйте этот метод, чтобы отправить аудио, если вы хотите, чтобы " +"клиенты (приложения) Telegram проигрывали их в музыкальном проигрывателе." +" Ваше аудио должно быть в формате .MP3 или .M4A. В случае успеха " +"возвращается отправленное сообщение (Message). На текущий момент, боты " +"могут отправлять аудио весом до 50 MB, это ограничение может измениться в" +" будущем." #: of telebot.TeleBot.send_audio:5 msgid "For sending voice messages, use the send_voice method instead." @@ -4105,9 +4308,9 @@ msgid "" "format." msgstr "" "Аудио для отправки. Передайте file_id (String), чтобы отправить аудио, " -"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить аудио из интернета или загрузите новое с помощью " -"multipart/form-data. Аудио должно быть в формате .MP3 или .M4A." +"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить аудио из интернета или загрузите новое с " +"помощью multipart/form-data. Аудио должно быть в формате .MP3 или .M4A." #: of telebot.TeleBot.send_audio:17 msgid "Audio caption, 0-1024 characters after entities parsing" @@ -4130,8 +4333,8 @@ msgid "" "Mode for parsing entities in the audio caption. See formatting options " "for more details." msgstr "" -"Режим форматирования подписи к аудио. См. formatting options " -"для получения подробностей." +"Режим форматирования подписи к аудио. См. formatting options для " +"получения подробностей." #: of telebot.TeleBot.send_audio:45 msgid "" @@ -4146,10 +4349,11 @@ msgstr "" "Обложка отправленного файла; может быть проигнорирована, если генерация " "обложки поддерживается на стороне сервера. Обложка должна быть картинкой " "в формате JPEG и весить менее 200 kB. Ширина и высота обложки не должны " -"превышать 320. Игнорируется, если файл не загружен с помощью multipart/form-" -"data. Обложки не могут быть использованы повторно и могут быть загружены " -"только как новый файл, так что вы можете передать “attach://” " -"если обложка была загружена с помощью multipart/form-data под именем ." +"превышать 320. Игнорируется, если файл не загружен с помощью multipart" +"/form-data. Обложки не могут быть использованы повторно и могут быть " +"загружены только как новый файл, так что вы можете передать " +"“attach://” если обложка была загружена с помощью " +"multipart/form-data под именем ." #: of telebot.TeleBot.send_audio:51 telebot.TeleBot.send_document:35 #: telebot.TeleBot.send_photo:19 telebot.TeleBot.send_voice:37 @@ -4157,8 +4361,8 @@ msgid "" "A JSON-serialized list of special entities that appear in the caption, " "which can be specified instead of parse_mode" msgstr "" -"Список отформатированных частей подписи в формате JSON, можно использовать вместо " -"parse_mode" +"Список отформатированных частей подписи в формате JSON, можно " +"использовать вместо parse_mode" #: of telebot.TeleBot.send_chat_action:1 msgid "" @@ -4169,8 +4373,8 @@ msgid "" msgstr "" "Используйте этот метод, когда вам нужно показать пользователю, что бот " "что-то делает. Статус устанавливается на 5 секунд или менее (когда от " -"бота приходит сообщение, клиенты (приложения) Telegram убирают статус typing). " -"Возвращает True в случае успеха." +"бота приходит сообщение, клиенты (приложения) Telegram убирают статус " +"typing). Возвращает True в случае успеха." #: of telebot.TeleBot.send_chat_action:5 msgid "" @@ -4181,8 +4385,9 @@ msgid "" msgstr "" "Пример: ImageBot-у требуется время, чтобы обработать запрос и загрузить " "изображение. Вместо отправки текстового сообщения “Отправка изображения, " -"пожалуйста подождите…”, бот может использовать sendChatAction с параметром " -"action = upload_photo. Пользователь увидит статус бота “sending photo”." +"пожалуйста подождите…”, бот может использовать sendChatAction с " +"параметром action = upload_photo. Пользователь увидит статус бота " +"“sending photo”." #: of telebot.TeleBot.send_chat_action:8 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendchataction" @@ -4205,13 +4410,12 @@ msgid "" msgstr "" "Тип действия. Выберите один, в зависимости от того, что получит " "пользователь: typing для текстовых сообщений, upload_photo для фото, " -"record_video или upload_video для видео, record_voice или upload_voice для " -"голосовых сообщений, upload_document для файлов, choose_sticker для " -"стикеров, find_location для данных о местоположении, record_video_note или " -"upload_video_note для видео заметок (кружочков)." +"record_video или upload_video для видео, record_voice или upload_voice " +"для голосовых сообщений, upload_document для файлов, choose_sticker для " +"стикеров, find_location для данных о местоположении, record_video_note " +"или upload_video_note для видео заметок (кружочков)." #: of telebot.TeleBot.send_chat_action:22 - msgid "" "The thread identifier of a message from which the reply will be " "sent(supergroups only)" @@ -4222,8 +4426,8 @@ msgid "" "Use this method to send phone contacts. On success, the sent Message is " "returned." msgstr "" -"Используйте этот метод, чтобы отправить контакт. В случае успеха возвращается " -"отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить контакт. В случае успеха " +"возвращается отправленное сообщение (Message)." #: of telebot.TeleBot.send_contact:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendcontact" @@ -4251,8 +4455,8 @@ msgid "" "Pass True, if the message should be sent even if one of the specified " "replied-to messages is not found." msgstr "" -"Передайте True, если сообщение должно быть отправлено даже если одно из сообщений, " -"на которые нужно ответить, не найдено." +"Передайте True, если сообщение должно быть отправлено даже если одно из " +"сообщений, на которые нужно ответить, не найдено." #: of telebot.TeleBot.send_contact:41 telebot.TeleBot.send_venue:54 msgid "The thread identifier of a message from which the reply will be sent" @@ -4263,8 +4467,9 @@ msgid "" "Use this method to send an animated emoji that will display a random " "value. On success, the sent Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить анимированный эмодзи, который покажет " -"случайное значение. В случае успеха возвращается отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить анимированный эмодзи, который " +"покажет случайное значение. В случае успеха возвращается отправленное " +"сообщение (Message)." #: of telebot.TeleBot.send_dice:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#senddice" @@ -4277,9 +4482,9 @@ msgid "" " and “🎳”, values 1-5 for “🏀” and “⚽”, and values 1-64 for “🎰”. Defaults " "to “🎲”" msgstr "" -"Эмодзи, на котором основана анимация. На текущий момент, должно быть одним из " -"“🎲”, “🎯”, “🏀”, “⚽”, “🎳”, или “🎰”. Значение может быть 1-6 для “🎲”, “🎯”" -" и “🎳”, 1-5 для “🏀” и “⚽”, и 1-64 для “🎰”. По умолчанию “🎲”" +"Эмодзи, на котором основана анимация. На текущий момент, должно быть " +"одним из “🎲”, “🎯”, “🏀”, “⚽”, “🎳”, или “🎰”. Значение может быть 1-6 для " +"“🎲”, “🎯” и “🎳”, 1-5 для “🏀” и “⚽”, и 1-64 для “🎰”. По умолчанию “🎲”" #: of telebot.TeleBot.send_dice:29 msgid "Protects the contents of the sent message from forwarding" @@ -4300,18 +4505,18 @@ msgid "" "String for Telegram to get a file from the Internet, or upload a new one " "using multipart/form-data" msgstr "" -"(документ) Файл для отправки. Передайте file_id (String), чтобы отправить файл, " -"который уже загружен на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить файл из интернета или загрузите новый с помощью " -"multipart/form-data" +"(документ) Файл для отправки. Передайте file_id (String), чтобы отправить" +" файл, который уже загружен на сервера Telegram (рекомендуется), " +"передайте HTTP URL (String), чтобы отправить файл из интернета или " +"загрузите новый с помощью multipart/form-data" #: of telebot.TeleBot.send_document:15 msgid "" "Document caption (may also be used when resending documents by file_id), " "0-1024 characters after entities parsing" msgstr "" -"Подпись к файлу (может быть использована при повторной отправке файла по file_id), " -"0-1024 символа после форматирования" +"Подпись к файлу (может быть использована при повторной отправке файла по " +"file_id), 0-1024 символа после форматирования" #: of telebot.TeleBot.send_document:23 msgid "Mode for parsing entities in the document caption" @@ -4328,29 +4533,30 @@ msgid "" "“attach://” if the thumbnail was uploaded using " "multipart/form-data under " msgstr "" -"InputFile или String : Обложка отправленного файла; может быть проигнорирована, " -"если генерация обложки поддерживается на стороне сервера. Обложка должна " -"быть картинкой в формате JPEG и весить менее 200 kB. Ширина и высота обложки " -"не должны превышать 320. Игнорируется, если файл не загружен с помощью " -"multipart/form-data. Обложки не могут быть использованы повторно и могут быть " -"загружены только как новый файл, так что вы можете передать " -"“attach://” если обложка была загружена с помощью " -"multipart/form-data под именем ." +"InputFile или String : Обложка отправленного файла; может быть " +"проигнорирована, если генерация обложки поддерживается на стороне " +"сервера. Обложка должна быть картинкой в формате JPEG и весить менее 200 " +"kB. Ширина и высота обложки не должны превышать 320. Игнорируется, если " +"файл не загружен с помощью multipart/form-data. Обложки не могут быть " +"использованы повторно и могут быть загружены только как новый файл, так " +"что вы можете передать “attach://” если обложка была " +"загружена с помощью multipart/form-data под именем ." #: of telebot.TeleBot.send_document:41 msgid "" "allows to define file name that will be visible in the Telegram instead " "of original file name" msgstr "" -"позволяет задать имя файла, которое будет показано в Telegram вместо настоящего" +"позволяет задать имя файла, которое будет показано в Telegram вместо " +"настоящего" #: of telebot.TeleBot.send_document:44 msgid "" "Disables automatic server-side content type detection for files uploaded " "using multipart/form-data" msgstr "" -"Отключает автоматическое обнаружение типа файла на стороне сервера для файлов, " -"загруженных с помощью multipart/form-data" +"Отключает автоматическое обнаружение типа файла на стороне сервера для " +"файлов, загруженных с помощью multipart/form-data" #: of telebot.TeleBot.send_document:47 telebot.TeleBot.send_sticker:33 #: telebot.TeleBot.send_video:55 @@ -4374,8 +4580,8 @@ msgid "" "Short name of the game, serves as the unique identifier for the game. Set" " up your games via @BotFather." msgstr "" -"Короткое имя игры, служит в качестве уникального id игры. Настройте свои игры" -"через @BotFather." +"Короткое имя игры, служит в качестве уникального id игры. Настройте свои " +"игрычерез @BotFather." #: of telebot.TeleBot.send_game:20 msgid "Timeout in seconds for waiting for a response from the bot." @@ -4386,7 +4592,8 @@ msgid "" "Pass True, if content of the message needs to be protected from being " "viewed by the bot." msgstr "" -"Передайте True, если содержимое сообщение должно быть защищено от просмотра ботом." +"Передайте True, если содержимое сообщение должно быть защищено от " +"просмотра ботом." #: of telebot.TeleBot.send_game:29 msgid "" @@ -4425,8 +4632,8 @@ msgid "" "a marketing image for a service. People like it better when they see what" " they are paying for." msgstr "" -"URL фото продукта. Может быть фото товаров или рекламным изображением сервиса. " -"Людям больше нравится, когда они видят, за что платят." +"URL фото продукта. Может быть фото товаров или рекламным изображением " +"сервиса. Людям больше нравится, когда они видят, за что платят." #: of telebot.TeleBot.send_invoice:73 msgid "" @@ -4434,9 +4641,9 @@ msgid "" " price' button will be shown. If not empty, the first button must be a " "Pay button" msgstr "" -"JSON-сериализованный объект inline клавиатуры. Если пустой, будет показана " -"одна кнопка 'Pay total price'. Если не пустой, первая кнопка должна быть " -"кнопкой для оплаты" +"JSON-сериализованный объект inline клавиатуры. Если пустой, будет " +"показана одна кнопка 'Pay total price'. Если не пустой, первая кнопка " +"должна быть кнопкой для оплаты" #: of telebot.TeleBot.send_invoice:81 telebot.TeleBot.set_webhook:39 msgid "Timeout of a request, defaults to None" @@ -4481,8 +4688,8 @@ msgid "" "For live locations, a direction in which the user is moving, in degrees. " "Must be between 1 and 360 if specified." msgstr "" -"Для live местоположений, направление, в котором пользователь двигается, в градусах. " -"Должно быть между 1 и 360, если указано." +"Для live местоположений, направление, в котором пользователь двигается, в" +" градусах. Должно быть между 1 и 360, если указано." #: of telebot.TeleBot.send_location:37 msgid "" @@ -4491,8 +4698,8 @@ msgid "" "if specified." msgstr "" "Для live местоположений, максимальное расстояние для уведомлений о " -"приближении другого участника чата, в метрах. Должно быть между 1 и 100000, " -"если указано." +"приближении другого участника чата, в метрах. Должно быть между 1 и " +"100000, если указано." #: of telebot.TeleBot.send_media_group:1 msgid "" @@ -4501,9 +4708,10 @@ msgid "" " messages of the same type. On success, an array of Messages that were " "sent is returned." msgstr "" -"Используйте этот метод, чтобы отправить группу фото, видео, файлов или аудио " -"как альбом. Файлы и аудио могут быть сгруппированы в альбом только с сообщениями " -"того же типа. В случае успеха возвращается массив отправленных сообщений (Message)." +"Используйте этот метод, чтобы отправить группу фото, видео, файлов или " +"аудио как альбом. Файлы и аудио могут быть сгруппированы в альбом только " +"с сообщениями того же типа. В случае успеха возвращается массив " +"отправленных сообщений (Message)." #: of telebot.TeleBot.send_media_group:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendmediagroup" @@ -4514,16 +4722,16 @@ msgid "" "A JSON-serialized array describing messages to be sent, must include 2-10" " items" msgstr "" -"JSON-сериализованный массив, описывающий сообщения для отправки, должен включать " -"от 2 до 10 элементов" +"JSON-сериализованный массив, описывающий сообщения для отправки, должен " +"включать от 2 до 10 элементов" #: of telebot.TeleBot.send_media_group:12 msgid "" "Sends the messages silently. Users will receive a notification with no " "sound." msgstr "" -"Отправить сообщение, при получении которого пользователя пользователи получат " -"уведомление без звука." +"Отправить сообщение, при получении которого пользователя пользователи " +"получат уведомление без звука." #: of telebot.TeleBot.send_media_group:27 msgid "Identifier of a message thread, in which the media group will be sent" @@ -4544,8 +4752,9 @@ msgid "" "characters, use the `split_string` or `smart_split` function in util.py." msgstr "" "Предупреждение: Не отправляйте больше 4096 символов в одном сообщении, " -"иначе вы рискуете получить ошибку HTTP 414. Если вам нужно отправить больше " -"4096 символов, используйте функцию `split_string` или `smart_split` из util.py." +"иначе вы рискуете получить ошибку HTTP 414. Если вам нужно отправить " +"больше 4096 символов, используйте функцию `split_string` или " +"`smart_split` из util.py." #: of telebot.TeleBot.send_message:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendmessage" @@ -4560,22 +4769,22 @@ msgid "" "List of special entities that appear in message text, which can be " "specified instead of parse_mode" msgstr "" -"Список отформатированных частей в тексте сообщения, " -"можно использовать вместо parse_mode" +"Список отформатированных частей в тексте сообщения, можно использовать " +"вместо parse_mode" #: of telebot.TeleBot.send_message:27 msgid "" "If True, the message content will be hidden for all users except for the " "target user" msgstr "" -"Если True, содержимое сообщения будет скрыто от всех пользователей, кроме " -"заданного" +"Если True, содержимое сообщения будет скрыто от всех пользователей, кроме" +" заданного" #: of telebot.TeleBot.send_photo:1 msgid "Use this method to send photos. On success, the sent Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить фото. В случае успеха возвращается " -"отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить фото. В случае успеха " +"возвращается отправленное сообщение (Message)." #: of telebot.TeleBot.send_photo:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendphoto" @@ -4591,25 +4800,25 @@ msgid "" "must be at most 20." msgstr "" "Фото для отправки. Передайте file_id (String), чтобы отправить фото, " -"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить фото из интернета или загрузите новое с помощью " -"multipart/form-data. Фото должно весить не более 10 MB. Ширина и высота фото не " -"должны суммарно превышать 10000. Отношение ширины и высоты должно быть не более 20." +"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить фото из интернета или загрузите новое с " +"помощью multipart/form-data. Фото должно весить не более 10 MB. Ширина и " +"высота фото не должны суммарно превышать 10000. Отношение ширины и высоты" +" должно быть не более 20." #: of telebot.TeleBot.send_photo:13 msgid "" "Photo caption (may also be used when resending photos by file_id), 0-1024" " characters after entities parsing" msgstr "" -"Подпись к фото (может быть использована при повторной отправке файла по file_id), " -"0-1024 символа после форматирования" +"Подпись к фото (может быть использована при повторной отправке файла по " +"file_id), 0-1024 символа после форматирования" #: of telebot.TeleBot.send_photo:16 msgid "Mode for parsing entities in the photo caption." msgstr "Режим форматирования подписи к фото." #: of telebot.TeleBot.send_photo:45 - msgid "Pass True, if the photo should be sent as a spoiler" msgstr "Передайте True, если фото должно быть отправлено как спойлер" @@ -4618,8 +4827,8 @@ msgid "" "Use this method to send a native poll. On success, the sent Message is " "returned." msgstr "" -"Используйте этот метод, чтобы отправить опрос. В случае успеха возвращается " -"отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить опрос. В случае успеха " +"возвращается отправленное сообщение (Message)." #: of telebot.TeleBot.send_poll:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendpoll" @@ -4648,16 +4857,16 @@ msgid "" "True, if the poll allows multiple answers, ignored for polls in quiz " "mode, defaults to False" msgstr "" -"True, если опрос позволяет выбрать несколько вариантов ответа, игнорируется в " -"опросах вида “quiz”, по умолчанию False" +"True, если опрос позволяет выбрать несколько вариантов ответа, " +"игнорируется в опросах вида “quiz”, по умолчанию False" #: of telebot.TeleBot.send_poll:24 msgid "" "0-based identifier of the correct answer option. Available only for polls" " in quiz mode, defaults to None" msgstr "" -"Индекс правильного варианта ответа, начиная с 0. Доступно только для опросов " -"вида “quiz”, по умолчанию None" +"Индекс правильного варианта ответа, начиная с 0. Доступно только для " +"опросов вида “quiz”, по умолчанию None" #: of telebot.TeleBot.send_poll:28 msgid "" @@ -4682,8 +4891,8 @@ msgid "" "Amount of time in seconds the poll will be active after creation, 5-600. " "Can't be used together with close_date." msgstr "" -"Время в секундах, в течение которого опрос будет активен, 5-600. " -"Нельзя использовать вместо с close_date." +"Время в секундах, в течение которого опрос будет активен, 5-600. Нельзя " +"использовать вместо с close_date." #: of telebot.TeleBot.send_poll:38 msgid "Point in time (Unix timestamp) when the poll will be automatically closed." @@ -4694,12 +4903,14 @@ msgid "" "Pass True, if the poll needs to be immediately closed. This can be useful" " for poll preview." msgstr "" -"Передайте True, если опрос должен быть завершен немедленно. Может быть полезно " -"для предпросмотра опроса." +"Передайте True, если опрос должен быть завершен немедленно. Может быть " +"полезно для предпросмотра опроса." #: of telebot.TeleBot.send_poll:50 msgid "Pass True, if the poll allows multiple options to be voted simultaneously." -msgstr "Передайте True, если опрос позволяет выбрать несколько вариантов одновременно." +msgstr "" +"Передайте True, если опрос позволяет выбрать несколько вариантов " +"одновременно." #: of telebot.TeleBot.send_poll:57 msgid "Timeout in seconds for waiting for a response from the user." @@ -4710,8 +4921,8 @@ msgid "" "A JSON-serialized list of special entities that appear in the " "explanation, which can be specified instead of parse_mode" msgstr "" -"JSON-сериализованный список отформатированных частей explanation, " -"можно использовать вместо parse_mode" +"JSON-сериализованный список отформатированных частей explanation, можно " +"использовать вместо parse_mode" #: of telebot.TeleBot.send_poll:67 msgid "The identifier of a message thread, in which the poll will be sent" @@ -4722,8 +4933,8 @@ msgid "" "Use this method to send static .WEBP, animated .TGS, or video .WEBM " "stickers. On success, the sent Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить статичный .WEBP, анимированный .TGS, " -"или видео .WEBM стикер. В случае успеха возвращает отправленное " +"Используйте этот метод, чтобы отправить статичный .WEBP, анимированный " +".TGS, или видео .WEBM стикер. В случае успеха возвращает отправленное " "сообщение (Message)." #: of telebot.TeleBot.send_sticker:4 @@ -4738,21 +4949,25 @@ msgid "" " multipart/form-data." msgstr "" "Стикер для отправки. Передайте file_id (String), чтобы отправить файл, " -"который уже загружен на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить .webp файл из интернета или загрузите новый с помощью " -"multipart/form-data." +"который уже загружен на сервера Telegram (рекомендуется), передайте HTTP " +"URL (String), чтобы отправить .webp файл из интернета или загрузите новый" +" с помощью multipart/form-data." #: of telebot.TeleBot.send_sticker:21 msgid "to disable the notification" msgstr "отключить уведомление" +#: of telebot.TeleBot.send_sticker:39 +msgid "Emoji associated with the sticker; only for just uploaded stickers" +msgstr "" + #: of telebot.TeleBot.send_venue:1 msgid "" "Use this method to send information about a venue. On success, the sent " "Message is returned." msgstr "" -"Используйте этот метод, чтобы отправить информацию о месте. В случае успеха " -"возвращается отправленное сообщение (Message)." +"Используйте этот метод, чтобы отправить информацию о месте. В случае " +"успеха возвращается отправленное сообщение (Message)." #: of telebot.TeleBot.send_venue:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvenue" @@ -4801,8 +5016,9 @@ msgid "" "Use this method to send video files, Telegram clients support mp4 videos " "(other formats may be sent as Document)." msgstr "" -"Используйте этот метод, чтобы отправить видео, клиенты (приложения) Telegram " -"поддерживают mp4 видео (другие форматы могут быть отправлены как Document)." +"Используйте этот метод, чтобы отправить видео, клиенты (приложения) " +"Telegram поддерживают mp4 видео (другие форматы могут быть отправлены как" +" Document)." #: of telebot.TeleBot.send_video:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideo" @@ -4835,8 +5051,8 @@ msgid "" "Video caption (may also be used when resending videos by file_id), 0-1024" " characters after entities parsing" msgstr "" -"Подпись к видео (может быть использована при повторной отправке файла по file_id), " -"0-1024 символа после форматирования" +"Подпись к видео (может быть использована при повторной отправке файла по " +"file_id), 0-1024 символа после форматирования" #: of telebot.TeleBot.send_video:26 msgid "Mode for parsing entities in the video caption" @@ -4847,7 +5063,6 @@ msgid "Pass True, if the uploaded video is suitable for streaming" msgstr "Передайте True, если загруженное видео подходит для стриминга" #: of telebot.TeleBot.send_video:61 - msgid "Pass True, if the video should be sent as a spoiler" msgstr "Передайте True, если видео должно быть отправлено как спойлер" @@ -4857,15 +5072,31 @@ msgid "" "to 1 minute long. Use this method to send video messages. On success, the" " sent Message is returned." msgstr "" -"Начиная с версии v.4.0, клиенты(приложения) Telegram поддерживают скругленные " -"квадратные MPEG4 видео длительностью до минуты. Используйте этот метод, чтобы " -"отправить видео заметку (кружочек). В случае успеха возвращается отправленное " -"сообщение (Message)." +"Начиная с версии v.4.0, клиенты(приложения) Telegram поддерживают " +"скругленные квадратные MPEG4 видео длительностью до минуты. Используйте " +"этот метод, чтобы отправить видео заметку (кружочек). В случае успеха " +"возвращается отправленное сообщение (Message)." #: of telebot.TeleBot.send_video_note:4 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideonote" msgstr "Документация Telegram: https://core.telegram.org/bots/api#sendvideonote" +#: of telebot.TeleBot.send_video_note +msgid "param chat_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type chat_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note:7 +msgid ":obj:`int` or :obj:`str`" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param data" +msgstr "" + #: of telebot.TeleBot.send_video_note:9 msgid "" "Video note to send. Pass a file_id as String to send a video note that " @@ -4873,19 +5104,125 @@ msgid "" "multipart/form-data. Sending video notes by a URL is currently " "unsupported" msgstr "" -"Видео заметка для отправки. Передайте file_id (String), чтобы отправить видео " -"заметку, которая уже загружена на сервера Telegram или загрузите новую с помощью " -"multipart/form-data. На текущий момент, отправка видео заметок по URL не " -"поддерживается" +"Видео заметка для отправки. Передайте file_id (String), чтобы отправить " +"видео заметку, которая уже загружена на сервера Telegram или загрузите " +"новую с помощью multipart/form-data. На текущий момент, отправка видео " +"заметок по URL не поддерживается" + +#: of telebot.TeleBot.send_video_note +#, fuzzy +msgid "type data" +msgstr "тип" + +#: of telebot.TeleBot.send_video_note:11 telebot.TeleBot.send_video_note:37 +#, fuzzy +msgid ":obj:`str` or :class:`telebot.types.InputFile`" +msgstr "Список объектов :class:`telebot.types.Update`." + +#: of telebot.TeleBot.send_video_note +msgid "param duration" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type duration" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param length" +msgstr "" #: of telebot.TeleBot.send_video_note:16 msgid "Video width and height, i.e. diameter of the video message" msgstr "Ширина и высота видео (диаметр видео сообщения)" +#: of telebot.TeleBot.send_video_note +msgid "type length" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param reply_to_message_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type reply_to_message_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param reply_markup" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type reply_markup" +msgstr "" + +#: of telebot.TeleBot.send_video_note:24 +msgid "" +":class:`telebot.types.InlineKeyboardMarkup` or " +":class:`telebot.types.ReplyKeyboardMarkup` or " +":class:`telebot.types.ReplyKeyboardRemove` or " +":class:`telebot.types.ForceReply`" +msgstr "" + +#: of telebot.TeleBot.send_video_note +#, fuzzy +msgid "param disable_notification" +msgstr "отключить уведомление" + +#: of telebot.TeleBot.send_video_note +#, fuzzy +msgid "type disable_notification" +msgstr "отключить уведомление" + +#: of telebot.TeleBot.send_video_note +msgid "param timeout" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type timeout" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param thumbnail" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type thumbnail" +msgstr "" + +#: of telebot.TeleBot.send_video_note +#, fuzzy +msgid "param allow_sending_without_reply" +msgstr "Глобальное значение allow_sending_without_reply, по умолчанию None" + +#: of telebot.TeleBot.send_video_note +#, fuzzy +msgid "type allow_sending_without_reply" +msgstr "Глобальное значение allow_sending_without_reply, по умолчанию None" + +#: of telebot.TeleBot.send_video_note +msgid "param protect_content" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "type protect_content" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param message_thread_id" +msgstr "" + #: of telebot.TeleBot.send_video_note:45 msgid "Identifier of a message thread, in which the video note will be sent" msgstr "id топика, в который будет отправлена видео заметка" +#: of telebot.TeleBot.send_video_note +msgid "type message_thread_id" +msgstr "" + +#: of telebot.TeleBot.send_video_note +msgid "param thumb" +msgstr "" + #: of telebot.TeleBot.send_voice:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -4898,9 +5235,9 @@ msgstr "" "Используйте этот метод, чтобы отправить голосовое сообщение. Ваше аудио " "должно быть в формате .OGG и закодировано с помощью OPUS (другие форматы " "можно отправить как Audio или Document). В случае успеха возвращается " -"отправленное сообщение (Message). На текущий момент, боты могут отправлять " -"голосовые сообщения весом до 50 MB, это ограничение может быть изменено в " -"будущем." +"отправленное сообщение (Message). На текущий момент, боты могут " +"отправлять голосовые сообщения весом до 50 MB, это ограничение может быть" +" изменено в будущем." #: of telebot.TeleBot.send_voice:5 msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvoice" @@ -4914,9 +5251,9 @@ msgid "" "multipart/form-data." msgstr "" "Аудио для отправки. Передайте file_id (String), чтобы отправить аудио, " -"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP URL " -"(String), чтобы отправить аудио из интернета или загрузите новое с помощью " -"multipart/form-data." +"которое уже загружено на сервера Telegram (рекомендуется), передайте HTTP" +" URL (String), чтобы отправить аудио из интернета или загрузите новое с " +"помощью multipart/form-data." #: of telebot.TeleBot.send_voice:14 msgid "Voice message caption, 0-1024 characters after entities parsing" @@ -4931,8 +5268,8 @@ msgid "" "Mode for parsing entities in the voice message caption. See formatting " "options for more details." msgstr "" -"Режим форматирования подписи к голосовому сообщению. См. formatting options " -"для получения подробностей." +"Режим форматирования подписи к голосовому сообщению. См. formatting " +"options для получения подробностей." #: of telebot.TeleBot.set_chat_administrator_custom_title:1 msgid "" @@ -4954,9 +5291,7 @@ msgstr "" msgid "" "New custom title for the administrator; 0-16 characters, emoji are not " "allowed" -msgstr "" -"Новое кастомное звание администратора; 0-16 символов, эмодзи не " -"разрешены" +msgstr "Новое кастомное звание администратора; 0-16 символов, эмодзи не разрешены" #: of telebot.TeleBot.set_chat_description:1 msgid "" @@ -5001,14 +5336,16 @@ msgid "" "Unique identifier for the target private chat. If not specified, default " "bot's menu button will be changed." msgstr "" -"Уникальный id приватного чата. Если не указан, будет изменена кнопка меню " -"по умолчанию." +"Уникальный id приватного чата. Если не указан, будет изменена кнопка меню" +" по умолчанию." #: of telebot.TeleBot.set_chat_menu_button:11 msgid "" "A JSON-serialized object for the new bot's menu button. Defaults to " "MenuButtonDefault" -msgstr "JSON-сериализованный объект новой кнопки меню. По умолчанию MenuButtonDefault" +msgstr "" +"JSON-сериализованный объект новой кнопки меню. По умолчанию " +"MenuButtonDefault" #: of telebot.TeleBot.set_chat_permissions:1 msgid "" @@ -5016,9 +5353,9 @@ msgid "" "must be an administrator in the group or a supergroup for this to work " "and must have the can_restrict_members admin rights." msgstr "" -"Используйте этот метод, чтобы задать права по умолчанию для всех участников чата. " -"Бот должен быть администратором группы или супергруппы и иметь права администратора " -"can_restrict_members." +"Используйте этот метод, чтобы задать права по умолчанию для всех " +"участников чата. Бот должен быть администратором группы или супергруппы и" +" иметь права администратора can_restrict_members." #: of telebot.TeleBot.set_chat_permissions:5 msgid "" @@ -5041,11 +5378,11 @@ msgid "" "only work if the ‘All Members Are Admins’ setting is off in the target " "group." msgstr "" -"Используйте этот метод, чтобы задать новую аватарку чата. В приватных чатах " -"аватарки менять нельзя. Бот должен быть администратором чата и иметь " -"соответствующие права администратора. Возвращает True в случае успеха. " -"Примечание: В обычных группах (не супергруппы), этот метод будет работать " -"только если настройка ‘All Members Are Admins’ отключена." +"Используйте этот метод, чтобы задать новую аватарку чата. В приватных " +"чатах аватарки менять нельзя. Бот должен быть администратором чата и " +"иметь соответствующие права администратора. Возвращает True в случае " +"успеха. Примечание: В обычных группах (не супергруппы), этот метод будет " +"работать только если настройка ‘All Members Are Admins’ отключена." #: of telebot.TeleBot.set_chat_photo:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#setchatphoto" @@ -5063,10 +5400,11 @@ msgid "" "optionally returned in getChat requests to check if the bot can use this " "method. Returns True on success." msgstr "" -"Используйте этот метод, чтобы задать стикерпак супергруппы. Бот должен быть " -"администратором чата и иметь соответствующие права администратора. " -"Используйте атрибут can_set_sticker_set, возвращаемые методом getChat, чтобы " -"проверить, что бот может использовать этот метод. Возвращает True в случае успеха." +"Используйте этот метод, чтобы задать стикерпак супергруппы. Бот должен " +"быть администратором чата и иметь соответствующие права администратора. " +"Используйте атрибут can_set_sticker_set, возвращаемые методом getChat, " +"чтобы проверить, что бот может использовать этот метод. Возвращает True в" +" случае успеха." #: of telebot.TeleBot.set_chat_sticker_set:5 msgid "" @@ -5095,8 +5433,8 @@ msgstr "" "Используйте этот метод, чтобы изменить название чата. В приватных чатах " "изменить название нельзя. Бот должен быть администратором чата и иметь " "соответствующие права админа. Возвращает True в случае успеха. " -"Примечание: В обычных группах (не супергруппы), этот метод будет работать " -"только если настройка ‘All Members Are Admins’ отключена." +"Примечание: В обычных группах (не супергруппы), этот метод будет работать" +" только если настройка ‘All Members Are Admins’ отключена." #: of telebot.TeleBot.set_chat_title:7 msgid "Telegram documentation: https://core.telegram.org/bots/api#setchattitle" @@ -5106,6 +5444,22 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#se msgid "New chat title, 1-255 characters" msgstr "Новое название чата, 1-255 символов" +#: of telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:1 +#, fuzzy +msgid "" +"Use this method to set the thumbnail of a custom emoji sticker set. " +"Returns True on success." +msgstr "" +"Используйте этот метод, чтобы задать обложку стикерпака. Анимированные " +"обложки могут быть заданы только для анимированных стикерпаков. " +"Возвращает True в случае успеха." + +#: of telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:7 +msgid "" +"Custom emoji identifier of a sticker from the sticker set; pass an empty " +"string to drop the thumbnail and use the first sticker as the thumbnail." +msgstr "" + #: of telebot.TeleBot.set_game_score:1 msgid "Sets the value of points in the game to a specific user." msgstr "Задаёт количество очков пользователя в игре." @@ -5123,8 +5477,8 @@ msgid "" "Pass True, if the high score is allowed to decrease. This can be useful " "when fixing mistakes or banning cheaters" msgstr "" -"Передайте True, если количество очков могут быть уменьшено. Может быть полезно " -"при исправлении ошибок или бане читеров" +"Передайте True, если количество очков могут быть уменьшено. Может быть " +"полезно при исправлении ошибок или бане читеров" #: of telebot.TeleBot.set_game_score:23 msgid "" @@ -5139,8 +5493,8 @@ msgid "" "On success, if the message was sent by the bot, returns the edited " "Message, otherwise returns True." msgstr "" -"В случае успеха, если сообщение было отправлено ботом, возвращает измененное " -"сообщение (Message), иначе возвращает True." +"В случае успеха, если сообщение было отправлено ботом, возвращает " +"измененное сообщение (Message), иначе возвращает True." #: of telebot.TeleBot.set_my_commands:1 msgid "Use this method to change the list of the bot's commands." @@ -5161,10 +5515,11 @@ msgid "" "rights will be suggested to users, but they are are free to modify the " "list before adding the bot. Returns True on success." msgstr "" -"Используйте этот метод, чтобы изменить права администратора по умолчанию, " -"запрашиваемые при добавлении бота в группу или канал в качестве администратора. " -"Эти права будут предложены пользователям, но пользователи могут изменить список " -"перед добавлением бота. Возвращает True в случае успеха." +"Используйте этот метод, чтобы изменить права администратора по умолчанию," +" запрашиваемые при добавлении бота в группу или канал в качестве " +"администратора. Эти права будут предложены пользователям, но пользователи" +" могут изменить список перед добавлением бота. Возвращает True в случае " +"успеха." #: of telebot.TeleBot.set_my_default_administrator_rights:7 msgid "" @@ -5179,8 +5534,9 @@ msgid "" "A JSON-serialized object describing new default administrator rights. If " "not specified, the default administrator rights will be cleared." msgstr "" -"JSON-сериалиованный объект, описывающий новые права администратора по умолчанию. " -"Если не указан, права администратора по умолчанию будут сброшены." +"JSON-сериалиованный объект, описывающий новые права администратора по " +"умолчанию. Если не указан, права администратора по умолчанию будут " +"сброшены." #: of telebot.TeleBot.set_my_default_administrator_rights:13 msgid "" @@ -5188,8 +5544,105 @@ msgid "" "channels. Otherwise, the default administrator rights of the bot for " "groups and supergroups will be changed." msgstr "" -"Передайте True, чтобы изменить права администратора по умолчанию в каналах. " -"Иначе, будут изменены права администратора по умолчанию для групп и супергрупп." +"Передайте True, чтобы изменить права администратора по умолчанию в " +"каналах. Иначе, будут изменены права администратора по умолчанию для " +"групп и супергрупп." + +#: of telebot.TeleBot.set_my_description:1 +#, fuzzy +msgid "" +"Use this method to change the bot's description, which is shown in the " +"chat with the bot if the chat is empty. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы изменить кнопку меню в приватном чате или " +"кнопку меню по умолчанию. Возвращает True в случае успеха." + +#: of telebot.TeleBot.set_my_description:5 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmydescription" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#setchatdescription" + +#: of telebot.TeleBot.set_my_description:7 +msgid "" +"New bot description; 0-512 characters. Pass an empty string to remove the" +" dedicated description for the given language." +msgstr "" + +#: of telebot.TeleBot.set_my_description:10 +#, fuzzy +msgid "" +"A two-letter ISO 639-1 language code. If empty, the description will be " +"applied to all users for whose language there is no dedicated " +"description." +msgstr "" +"Двухбуквенный языковой код в формате ISO 639-1. Если не задан, изменения " +"коснутся команд для всех пользователей в заданном поле видимости, не " +"имеющих команд на их языке" + +#: of telebot.TeleBot.set_my_name:1 +#, fuzzy +msgid "Use this method to change the bot's name. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы изменить кнопку меню в приватном чате или " +"кнопку меню по умолчанию. Возвращает True в случае успеха." + +#: of telebot.TeleBot.set_my_name:3 +#, fuzzy +msgid "Telegram documentation: https://core.telegram.org/bots/api#setmyname" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#sendgame" + +#: of telebot.TeleBot.set_my_name:5 +msgid "" +"Optional. New bot name; 0-64 characters. Pass an empty string to remove " +"the dedicated name for the given language." +msgstr "" + +#: of telebot.TeleBot.set_my_name:8 +#, fuzzy +msgid "" +"Optional. A two-letter ISO 639-1 language code. If empty, the name will " +"be shown to all users for whose language there is no dedicated name." +msgstr "" +"Двухбуквенный языковой код в формате ISO 639-1. Если не задан, изменения " +"коснутся команд для всех пользователей в заданном поле видимости, не " +"имеющих команд на их языке" + +#: of telebot.TeleBot.set_my_short_description:1 +msgid "" +"Use this method to change the bot's short description, which is shown on " +"the bot's profile page and is sent together with the link when users " +"share the bot. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_my_short_description:5 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmyshortdescription" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#setchatdescription" + +#: of telebot.TeleBot.set_my_short_description:7 +msgid "" +"New short description for the bot; 0-120 characters. Pass an empty string" +" to remove the dedicated short description for the given language." +msgstr "" + +#: of telebot.TeleBot.set_my_short_description:10 +#, fuzzy +msgid "" +"A two-letter ISO 639-1 language code. If empty, the short description " +"will be applied to all users for whose language there is no dedicated " +"short description." +msgstr "" +"Двухбуквенный языковой код в формате ISO 639-1. Если не задан, изменения " +"коснутся команд для всех пользователей в заданном поле видимости, не " +"имеющих команд на их языке" #: of telebot.TeleBot.set_state:1 msgid "Sets a new state of a user." @@ -5203,21 +5656,78 @@ msgid "" "chat with a bot." msgstr "" "Вы должны указать и user id и chat id, чтобы задать состояние (стейт) " -"пользователя в чате. Иначе, если вы укажете только user_id, chat_id будет " -"равен user_id, что означает смену состояния (стейта) пользователя в его " +"пользователя в чате. Иначе, если вы укажете только user_id, chat_id будет" +" равен user_id, что означает смену состояния (стейта) пользователя в его " "приватном чате с ботом." #: of telebot.TeleBot.set_state:12 msgid "new state. can be string, integer, or :class:`telebot.types.State`" -msgstr "новое состояние (стейт). может быть строкой, числом или :class:`telebot.types.State`" +msgstr "" +"новое состояние (стейт). может быть строкой, числом или " +":class:`telebot.types.State`" + +#: of telebot.TeleBot.set_sticker_emoji_list:1 +#, fuzzy +msgid "" +"Use this method to set the emoji list of a custom emoji sticker set. " +"Returns True on success." +msgstr "" +"Используйте этот метод, чтобы получить текущий список команд бота. " +"Возвращает список объектов BotCommand в случае успеха." + +#: of telebot.TeleBot.set_sticker_emoji_list:4 +#, fuzzy +msgid "Sticker identifier" +msgstr "id пользователя" + +#: of telebot.TeleBot.set_sticker_emoji_list:7 +#, fuzzy +msgid "List of emoji" +msgstr "список команд" + +#: of telebot.TeleBot.set_sticker_keywords:1 +msgid "" +"Use this method to change search keywords assigned to a regular or custom" +" emoji sticker. The sticker must belong to a sticker set created by the " +"bot. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_sticker_keywords:5 +#: telebot.TeleBot.set_sticker_mask_position:5 +#, fuzzy +msgid "File identifier of the sticker." +msgstr "id файла стикера" + +#: of telebot.TeleBot.set_sticker_keywords:8 +msgid "" +"A JSON-serialized list of 0-20 search keywords for the sticker with total" +" length of up to 64 characters" +msgstr "" + +#: of telebot.TeleBot.set_sticker_mask_position:1 +#, fuzzy +msgid "" +"Use this method to change the mask position of a mask sticker. The " +"sticker must belong to a sticker set that was created by the bot. Returns" +" True on success." +msgstr "" +"Используйте этот метод, чтобы удалить стикер из стикерпака, созданного " +"ботом. Возвращает True в случае успеха." + +#: of telebot.TeleBot.set_sticker_mask_position:8 +#, fuzzy +msgid "" +"A JSON-serialized object for position where the mask should be placed on " +"faces." +msgstr "Позиция для размещения маски на лицах в формате JSON" #: of telebot.TeleBot.set_sticker_position_in_set:1 msgid "" "Use this method to move a sticker in a set created by the bot to a " "specific position . Returns True on success." msgstr "" -"Используйте этот метод, чтобы передвинуть стикер в стикерпаке, созданном ботом, на заданную " -"позицию. Возвращает True в случае успеха." +"Используйте этот метод, чтобы передвинуть стикер в стикерпаке, созданном " +"ботом, на заданную позицию. Возвращает True в случае успеха." #: of telebot.TeleBot.set_sticker_position_in_set:3 msgid "" @@ -5231,17 +5741,17 @@ msgstr "" msgid "New sticker position in the set, zero-based" msgstr "Новая позиция стикера в стикерпаке, начиная с нуля" -#: of telebot.TeleBot.set_sticker_set_thumb:1 +#: of telebot.TeleBot.set_sticker_set_thumbnail:1 msgid "" "Use this method to set the thumbnail of a sticker set. Animated " "thumbnails can be set for animated sticker sets only. Returns True on " "success." msgstr "" "Используйте этот метод, чтобы задать обложку стикерпака. Анимированные " -"обложки могут быть заданы только для анимированных стикерпаков. Возвращает " -"True в случае успеха." +"обложки могут быть заданы только для анимированных стикерпаков. " +"Возвращает True в случае успеха." -#: of telebot.TeleBot.set_sticker_set_thumb:4 +#: of telebot.TeleBot.set_sticker_set_thumbnail:4 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#setstickersetthumb" @@ -5249,9 +5759,44 @@ msgstr "" "Документация Telegram: " "https://core.telegram.org/bots/api#setstickersetthumb" +#: of telebot.TeleBot.set_sticker_set_thumbnail:12 +msgid "" +"A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in " +"size and have a width and height of exactly 100px, or a .TGS animation " +"with a thumbnail up to 32 kilobytes in size (see " +"https://core.telegram.org/stickers#animated-sticker-requirements for " +"animated sticker technical requirements), or a WEBM video with the " +"thumbnail up to 32 kilobytes in size; see " +"https://core.telegram.org/stickers#video-sticker-requirements for video " +"sticker technical requirements. Pass a file_id as a String to send a file" +" that already exists on the Telegram servers, pass an HTTP URL as a " +"String for Telegram to get a file from the Internet, or upload a new one " +"using multipart/form-data. More information on Sending Files ». Animated " +"and video sticker set thumbnails can't be uploaded via HTTP URL. If " +"omitted, then the thumbnail is dropped and the first sticker is used as " +"the thumbnail." +msgstr "" + +#: of telebot.TeleBot.set_sticker_set_title:1 +#, fuzzy +msgid "" +"Use this method to set the title of a created sticker set. Returns True " +"on success." +msgstr "" +"Используйте этот метод, чтобы задать обложку стикерпака. Анимированные " +"обложки могут быть заданы только для анимированных стикерпаков. " +"Возвращает True в случае успеха." + +#: of telebot.TeleBot.set_sticker_set_title:7 +#, fuzzy +msgid "New sticker set title" +msgstr "Имя стикерпака" + #: of telebot.TeleBot.set_update_listener:1 msgid "Sets a listener function to be called when a new update is received." -msgstr "Задаёт функцию-листенер, которая будет вызвана при получении нового апдейта." +msgstr "" +"Задаёт функцию-листенер, которая будет вызвана при получении нового " +"апдейта." #: of telebot.TeleBot.set_update_listener:3 msgid "Listener function." @@ -5266,10 +5811,11 @@ msgid "" "reasonable amount of attempts. Returns True on success." msgstr "" "Используйте этот метод, чтобы задать URL и получать входящие апдейты с " -"помощью вебхука. Как только у бота появляется апдейт, он будет отправлен с " -"помощью HTTPS POST запроса на заданный URL, содержащего JSON-сериализованный " -"Update. В случае неудачного запроса, отправка апдейта будет отменена после " -"разумного числа попыток. Возвращает True в случае успеха." +"помощью вебхука. Как только у бота появляется апдейт, он будет отправлен " +"с помощью HTTPS POST запроса на заданный URL, содержащего " +"JSON-сериализованный Update. В случае неудачного запроса, отправка " +"апдейта будет отменена после разумного числа попыток. Возвращает True в " +"случае успеха." #: of telebot.TeleBot.set_webhook:6 msgid "" @@ -5279,8 +5825,8 @@ msgid "" "secret token as content." msgstr "" "Если вы хотите удостовериться, что вебхук был задан вами, вы можете " -"задать секретный токен в параметре secret_token. Если указан, запрос " -"с апдейтом будет содержать хедер “X-Telegram-Bot-Api-Secret-Token” с " +"задать секретный токен в параметре secret_token. Если указан, запрос с " +"апдейтом будет содержать хедер “X-Telegram-Bot-Api-Secret-Token” с " "секретным токеном в качестве значения." #: of telebot.TeleBot.set_webhook:9 @@ -5292,16 +5838,16 @@ msgid "" "HTTPS URL to send updates to. Use an empty string to remove webhook " "integration, defaults to None" msgstr "" -"HTTPS URL для отправки апдейтов. Используйте пустую строку, чтобы удалить " -"вебхук, по умолчанию None" +"HTTPS URL для отправки апдейтов. Используйте пустую строку, чтобы удалить" +" вебхук, по умолчанию None" #: of telebot.TeleBot.set_webhook:14 msgid "" "Upload your public key certificate so that the root certificate in use " "can be checked, defaults to None" msgstr "" -"Загрузите публичный ключ вашего SSL сертификата, чтобы корневой сертификат мог быть " -"проверен, по умолчанию None" +"Загрузите публичный ключ вашего SSL сертификата, чтобы корневой " +"сертификат мог быть проверен, по умолчанию None" #: of telebot.TeleBot.set_webhook:17 msgid "" @@ -5310,10 +5856,10 @@ msgid "" "limit the load on your bot's server, and higher values to increase your " "bot's throughput, defaults to None" msgstr "" -"Максимально-допустимое количество одновременных HTTPS соединений для доставки " -"апдейтов, 1-100. По умолчанию 40. Используйте меньшие значения для уменьшения " -"нагрузки на ваш сервер и большие значения, чтобы увеличить пропускную способность " -"вашего бота, по умолчанию None" +"Максимально-допустимое количество одновременных HTTPS соединений для " +"доставки апдейтов, 1-100. По умолчанию 40. Используйте меньшие значения " +"для уменьшения нагрузки на ваш сервер и большие значения, чтобы увеличить" +" пропускную способность вашего бота, по умолчанию None" #: of telebot.TeleBot.set_webhook:22 msgid "" @@ -5330,10 +5876,11 @@ msgstr "" "Например, укажите [“message”, “edited_channel_post”, “callback_query”], " "чтобы получать апдейты только этих видов. Полный список доступных видов " "апдейтов - util.update_types. Укажите пустой список, чтобы получать все " -"апдейты, кроме chat_member (по умолчанию). Если не задан, будет использована " -"последняя настройка. Пожалуйста учтите, чтобы этот параметр не влияет на апдейты, " -"отправленные до вызова setWebhooks, поэтому нежелательные апдейты могут быть " -"получены в течение короткого периода времени. По умолчанию None" +"апдейты, кроме chat_member (по умолчанию). Если не задан, будет " +"использована последняя настройка. Пожалуйста учтите, чтобы этот параметр " +"не влияет на апдейты, отправленные до вызова setWebhooks, поэтому " +"нежелательные апдейты могут быть получены в течение короткого периода " +"времени. По умолчанию None" #: of telebot.TeleBot.set_webhook:22 msgid "" @@ -5348,8 +5895,8 @@ msgstr "" "Например, укажите [“message”, “edited_channel_post”, “callback_query”], " "чтобы получать апдейты только этих видов. Полный список доступных видов " "апдейтов - util.update_types. Укажите пустой список, чтобы получать все " -"апдейты, кроме chat_member (по умолчанию). Если не задан, будет использована " -"последняя настройка." +"апдейты, кроме chat_member (по умолчанию). Если не задан, будет " +"использована последняя настройка." #: of telebot.TeleBot.set_webhook:27 msgid "" @@ -5357,9 +5904,9 @@ msgid "" " call to the setWebhook, so unwanted updates may be received for a short " "period of time. Defaults to None" msgstr "" -"Пожалуйста учтите, чтобы этот параметр не влияет на апдейты, " -"отправленные до вызова setWebhooks, поэтому нежелательные апдейты могут быть " -"получены в течение короткого периода времени. По умолчанию None" +"Пожалуйста учтите, чтобы этот параметр не влияет на апдейты, отправленные" +" до вызова setWebhooks, поэтому нежелательные апдейты могут быть получены" +" в течение короткого периода времени. По умолчанию None" #: of telebot.TeleBot.set_webhook:42 msgid "" @@ -5368,10 +5915,10 @@ msgid "" "0-9, _ and - are allowed. The header is useful to ensure that the request" " comes from a webhook set by you. Defaults to None" msgstr "" -"Секретный токен для отправки в хедере “X-Telegram-Bot-Api-Secret-Token” " -"в каждом запросе с апдейтом, 1-256 символов. Разрешены только символы A-Z, a-z, " -"0-9, _ и -. Хедер полезен для, того чтобы удостовериться, что запрос приходит" -"с вебхука, установленного вами. По умолчанию None" +"Секретный токен для отправки в хедере “X-Telegram-Bot-Api-Secret-Token” в" +" каждом запросе с апдейтом, 1-256 символов. Разрешены только символы A-Z," +" a-z, 0-9, _ и -. Хедер полезен для, того чтобы удостовериться, что " +"запрос приходитс вебхука, установленного вами. По умолчанию None" #: of telebot.TeleBot.set_webhook:47 msgid ":obj:`bool` if the request was successful." @@ -5391,8 +5938,8 @@ msgid "" "price. As a parameter to the decorator function, it passes " ":class:`telebot.types.ShippingQuery` object." msgstr "" -"Обрабатывает shipping query. Только для инвойсов с гибкой ценой. " -"В качестве параметра передаёт в декорируемую функцию объект " +"Обрабатывает shipping query. Только для инвойсов с гибкой ценой. В " +"качестве параметра передаёт в декорируемую функцию объект " ":class:`telebot.types.ShippingQuery`." #: of telebot.TeleBot.stop_bot:1 @@ -5405,9 +5952,10 @@ msgid "" "live_period expires. On success, if the message is not an inline message," " the edited Message is returned, otherwise True is returned." msgstr "" -"Используйте этот метод, чтобы остановить обновление live местоположения до " -"истечения live_period. В случае успеха, если сообщение не является inline сообщением," -"возвращается измененное сообщение (Message), иначе возвращается True." +"Используйте этот метод, чтобы остановить обновление live местоположения " +"до истечения live_period. В случае успеха, если сообщение не является " +"inline сообщением,возвращается измененное сообщение (Message), иначе " +"возвращается True." #: of telebot.TeleBot.stop_message_live_location:4 msgid "" @@ -5422,32 +5970,32 @@ msgid "" "Required if inline_message_id is not specified. Identifier of the message" " with live location to stop" msgstr "" -"Обязательный, если не указан inline_message_id. id сообщения live местоположением, " -"которое нужно остановить" +"Обязательный, если не указан inline_message_id. id сообщения live " +"местоположением, которое нужно остановить" #: of telebot.TeleBot.stop_message_live_location:12 msgid "" "Required if chat_id and message_id are not specified. Identifier of the " "inline message with live location to stop" msgstr "" -"Обязательный, если не указаны chat_id и message_id. id inline сообщения с live " -"местоположением, которое нужно остановить" +"Обязательный, если не указаны chat_id и message_id. id inline сообщения с" +" live местоположением, которое нужно остановить" #: of telebot.TeleBot.stop_message_live_location:22 msgid "" "On success, if the message is not an inline message, the edited Message " "is returned, otherwise True is returned." msgstr "" -"В случае успеха, если сообщение не является inline сообщением, возвращается " -"измененное сообщение (Message), иначе возвращается True." +"В случае успеха, если сообщение не является inline сообщением, " +"возвращается измененное сообщение (Message), иначе возвращается True." #: of telebot.TeleBot.stop_poll:1 msgid "" "Use this method to stop a poll which was sent by the bot. On success, the" " stopped Poll is returned." msgstr "" -"Используйте этот метод, чтобы завершить опрос, отправленный ботом. В случае успеха " -"возвращается завершенный опрос (Poll)." +"Используйте этот метод, чтобы завершить опрос, отправленный ботом. В " +"случае успеха возвращается завершенный опрос (Poll)." #: of telebot.TeleBot.stop_poll:3 msgid "Telegram documentation: https://core.telegram.org/bots/api#stoppoll" @@ -5488,11 +6036,12 @@ msgid "" " If you don't want this, use the parameter only_if_banned." msgstr "" "Используйте этот метод, чтобы разбанить ранее кикнутого пользователя в " -"супергруппе или канале. Пользовать не вернется в группу или канал автоматически, " -"но сможет присоединиться с помощью ссылки и т.д. Бот должен быть администратором. " -"По умолчанию, этот метод гарантирует, что после вызова, пользователь не является " -"участником чата, но может присоединиться. Поэтому если пользовать является участником " -"чата, он будет кикнут, но не забанен. Если вы хотите изменить это поведение, " +"супергруппе или канале. Пользовать не вернется в группу или канал " +"автоматически, но сможет присоединиться с помощью ссылки и т.д. Бот " +"должен быть администратором. По умолчанию, этот метод гарантирует, что " +"после вызова, пользователь не является участником чата, но может " +"присоединиться. Поэтому если пользовать является участником чата, он " +"будет кикнут, но не забанен. Если вы хотите изменить это поведение, " "используйте параметр only_if_banned." #: of telebot.TeleBot.unban_chat_member:7 @@ -5503,7 +6052,9 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#un msgid "" "Unique identifier for the target group or username of the target " "supergroup or channel (in the format @username)" -msgstr "Уникальный id группы или username супергруппы или канала (в формате @username)" +msgstr "" +"Уникальный id группы или username супергруппы или канала (в формате " +"@username)" #: of telebot.TeleBot.unban_chat_member:16 msgid "Do nothing if the user is not banned" @@ -5515,9 +6066,9 @@ msgid "" " or channel. The bot must be an administrator for this to work and must " "have the appropriate administrator rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы разбанить ране забаненный канал в супергруппе " -"или канала. Бот должен быть администратором и иметь соответствующие права " -"администратора. Возвращает True в случае успеха." +"Используйте этот метод, чтобы разбанить ране забаненный канал в " +"супергруппе или канала. Бот должен быть администратором и иметь " +"соответствующие права администратора. Возвращает True в случае успеха." #: of telebot.TeleBot.unban_chat_sender_chat:6 msgid "" @@ -5532,18 +6083,16 @@ msgid "Unique identifier of the target sender chat." msgstr "Уникальный id чата." #: of telebot.TeleBot.unhide_general_forum_topic:1 - msgid "" "Use this method to unhide the 'General' topic in a forum supergroup chat." " The bot must be an administrator in the chat for this to work and must " "have can_manage_topics administrator rights. Returns True on success." msgstr "" -"Используйте этот метод, чтобы сделать топик 'General' видимым в супергруппе " -"с топиками. Бот должен быть администратором чата и иметь права администратора " -"can_manage_topics. Возвращает True в случае успеха." +"Используйте этот метод, чтобы сделать топик 'General' видимым в " +"супергруппе с топиками. Бот должен быть администратором чата и иметь " +"права администратора can_manage_topics. Возвращает True в случае успеха." #: of telebot.TeleBot.unhide_general_forum_topic:5 - msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#unhidegeneralforumtopic" @@ -5557,9 +6106,9 @@ msgid "" "bot must be an administrator in the chat for this to work and must have " "the appropriate admin rights. Returns True on success." msgstr "" -"Используйте этот метод, что открепить все закрепленные сообщения в супергруппе. " -"Бот должен быть администратором чата и иметь соответствующие права администратора. " -"Возвращает True в случае успеха." +"Используйте этот метод, что открепить все закрепленные сообщения в " +"супергруппе. Бот должен быть администратором чата и иметь соответствующие" +" права администратора. Возвращает True в случае успеха." #: of telebot.TeleBot.unpin_all_chat_messages:5 msgid "" @@ -5576,9 +6125,9 @@ msgid "" "have the can_pin_messages administrator right in the supergroup. Returns " "True on success." msgstr "" -"Используйте этот метод, что открепить все закрепленные сообщения в топике. " -"Бот должен быть администратором чата и иметь права администратора " -"can_pin_messages в супергруппе. Возвращает True в случае успеха." +"Используйте этот метод, что открепить все закрепленные сообщения в " +"топике. Бот должен быть администратором чата и иметь права администратора" +" can_pin_messages в супергруппе. Возвращает True в случае успеха." #: of telebot.TeleBot.unpin_all_forum_topic_messages:5 msgid "" @@ -5598,17 +6147,15 @@ msgid "" "The bot must be an administrator in the chat for this to work and must " "have the appropriate admin rights. Returns True on success." msgstr "" -"Используйте этот метод, что открепить закрепленное сообщение в супергруппе. " -"Бот должен быть администратором чата и иметь соответствующие права администратора. " -"Возвращает True в случае успеха." +"Используйте этот метод, что открепить закрепленное сообщение в " +"супергруппе. Бот должен быть администратором чата и иметь соответствующие" +" права администратора. Возвращает True в случае успеха." #: of telebot.TeleBot.unpin_chat_message:5 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#unpinchatmessage" -msgstr "" -"Документация Telegram: " -"https://core.telegram.org/bots/api#unpinchatmessage" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#unpinchatmessage" #: of telebot.TeleBot.unpin_chat_message:11 msgid "Int: Identifier of a message to unpin" @@ -5622,7 +6169,8 @@ msgid "" msgstr "" "Используйте этот метод, чтобы загрузить .png стикер, чтобы позже " "использовать в методах createNewStickerSet и addStickerToSet (может быть " -"использован несколько раз). Возвращает загруженный файл (File) в случае успеха." +"использован несколько раз). Возвращает загруженный файл (File) в случае " +"успеха." #: of telebot.TeleBot.upload_sticker_file:4 msgid "" @@ -5637,15 +6185,28 @@ msgid "User identifier of sticker set owner" msgstr "id пользователя, создавшего стикерпак" #: of telebot.TeleBot.upload_sticker_file:9 +#, fuzzy msgid "" -"PNG image with the sticker, must be up to 512 kilobytes in size, " -"dimensions must not exceed 512px, and either width or height must be " -"exactly 512px." +"DEPRECATED: PNG image with the sticker, must be up to 512 kilobytes in " +"size, dimensions must not exceed 512px, and either width or height must " +"be exactly 512px." msgstr "" "PNG изображение стикера, должно весить не более 512 kB, измерения не " -"должны превышать 512px и либо ширина, либо высота должна быть ровно 512px." +"должны превышать 512px и либо ширина, либо высота должна быть ровно " +"512px." #: of telebot.TeleBot.upload_sticker_file:13 +msgid "" +"A file with the sticker in .WEBP, .PNG, .TGS, or .WEBM format. See " +"https://core.telegram.org/stickers for technical requirements. More " +"information on Sending Files »" +msgstr "" + +#: of telebot.TeleBot.upload_sticker_file:17 +msgid "One of \"static\", \"animated\", \"video\"." +msgstr "" + +#: of telebot.TeleBot.upload_sticker_file:20 msgid "On success, the sent file is returned." msgstr "В случае успеха возвращается отправленный файл." @@ -5681,9 +6242,10 @@ msgid "" " - filter failed. message: Message class text: Filter value given in " "handler" msgstr "" -"Базовый класс Advanced Custom Filter. Создайте класс наследник с методом check(). " -"Принимает два параметра, возвращает bool: True - фильтр пройден, False - фильтр " -"не пройден. message: класс Message text: значение фильтра, полученное в хендлере" +"Базовый класс Advanced Custom Filter. Создайте класс наследник с методом " +"check(). Принимает два параметра, возвращает bool: True - фильтр пройден," +" False - фильтр не пройден. message: класс Message text: значение " +"фильтра, полученное в хендлере" #: of telebot.custom_filters.AdvancedCustomFilter:7 #: telebot.custom_filters.SimpleCustomFilter:5 @@ -5756,8 +6318,9 @@ msgid "" "Accepts only message, returns bool value, that is compared with given in " "handler." msgstr "" -"Базовый класс Simple Custom Filter. Создайте класс наследник с методом check(). " -"Принимает только сообщение, возвращает bool, который сравнивается с заданным в хендлере." +"Базовый класс Simple Custom Filter. Создайте класс наследник с методом " +"check(). Принимает только сообщение, возвращает bool, который " +"сравнивается с заданным в хендлере." #: of telebot.custom_filters.SimpleCustomFilter:7 msgid "Example on creating a simple custom filter." @@ -5776,8 +6339,8 @@ msgid "" "Advanced text filter to check (types.Message, types.CallbackQuery, " "types.InlineQuery, types.Poll)" msgstr "" -"Advanced текстовый фильтр для проверки (types.Message, types.CallbackQuery, " -"types.InlineQuery, types.Poll)" +"Advanced текстовый фильтр для проверки (types.Message, " +"types.CallbackQuery, types.InlineQuery, types.Poll)" #: of telebot.custom_filters.TextFilter:3 msgid "example of usage is in examples/custom_filters/advanced_text_filter.py" @@ -5789,7 +6352,9 @@ msgstr "строка, True если текст объекта идентичен #: of telebot.custom_filters.TextFilter:8 msgid "list[str] or tuple[str], True if any string element of iterable is in text" -msgstr "list[str] или tuple[str], True если хотя бы один из элементов есть в тексте" +msgstr "" +"list[str] или tuple[str], True если хотя бы один из элементов есть в " +"тексте" #: of telebot.custom_filters.TextFilter:11 telebot.custom_filters.TextFilter:14 msgid "string, True if object's text starts with passed string" @@ -5820,8 +6385,8 @@ msgid "" "Base class for middleware. Your middlewares should be inherited from this" " class." msgstr "" -"Базовый класс для middleware. Ваши middleware должны быть унаследованы от " -"этого класса." +"Базовый класс для middleware. Ваши middleware должны быть унаследованы от" +" этого класса." #: of telebot.handler_backends.BaseMiddleware:4 msgid "" @@ -5832,16 +6397,16 @@ msgid "" msgstr "" "Задайте update_sensitive=True если хотите получать разные апдейты в " "разных функциях. Например, если вы хотите обрабатывать pre_process для " -"апдейтов вида message, вам нужно будет создать функцию pre_process_message " -"и т.д. Аналогично для post_process." +"апдейтов вида message, вам нужно будет создать функцию " +"pre_process_message и т.д. Аналогично для post_process." #: of telebot.handler_backends.BaseMiddleware:10 msgid "" "If you want to use middleware, you have to set use_class_middlewares=True" " in your TeleBot instance." msgstr "" -"Если вы хотите использовать middleware, вам нужно задать use_class_middlewares=True " -"в экземпляре класса TeleBot." +"Если вы хотите использовать middleware, вам нужно задать " +"use_class_middlewares=True в экземпляре класса TeleBot." #: of telebot.handler_backends.BaseMiddleware:13 msgid "Example of class-based middlewares." @@ -5854,16 +6419,16 @@ msgid "" "post_process in middlewares." msgstr "" "Класс для отмены апдейтов. Просто верните экземпляр этого класса в " -"middleware, чтобы пропустить апдейт. Апдейт пропустит хендлер и исполнение " -"post_process в middleware." +"middleware, чтобы пропустить апдейт. Апдейт пропустит хендлер и " +"исполнение post_process в middleware." #: of telebot.handler_backends.ContinueHandling:1 msgid "" "Class for continue updates in handlers. Just return instance of this " "class in handlers to continue process." msgstr "" -"Класс для продолжения обработки апдейта в хендлерах. Просто верните экземпляр " -"этого класса в хендлерах, чтобы продолжить обработку." +"Класс для продолжения обработки апдейта в хендлерах. Просто верните " +"экземпляр этого класса в хендлерах, чтобы продолжить обработку." #: of telebot.handler_backends.ContinueHandling:5 msgid "Example of using ContinueHandling" @@ -5896,16 +6461,16 @@ msgid "" "This file is used by TeleBot.run_webhooks() function. Fastapi is required" " to run this script." msgstr "" -"Этот файл используется функцией TeleBot.run_webhooks(). Для запуска этого " -"скрипта требуется Fastapi." +"Этот файл используется функцией TeleBot.run_webhooks(). Для запуска этого" +" скрипта требуется Fastapi." #: of telebot.ext.sync.webhooks.SyncWebhookListener.run_app:1 msgid "" "Run app with the given parameters to init. Not supposed to be used " "manually by user." msgstr "" -"Запустить приложение с заданными параметрами инициализации. Не предназначено " -"для использования пользователем." +"Запустить приложение с заданными параметрами инициализации. Не " +"предназначено для использования пользователем." #~ msgid "New name of the topic, 1-128 characters" #~ msgstr "Новое название топика, 1-128 символов" @@ -5923,3 +6488,17 @@ msgstr "" #~ msgid "The chat for which we want to handle new message." #~ msgstr "" +#~ msgid "" +#~ "Use this method to add a new " +#~ "sticker to a set created by the" +#~ " bot. It's required to pass " +#~ "`png_sticker` or `tgs_sticker`. Returns True" +#~ " on success." +#~ msgstr "" +#~ "Используйте этот метод, чтобы добавить " +#~ "новый стикер в стикерпак, созданный " +#~ "ботом. Необходимо передать либо `png_sticker`," +#~ " либо `tgs_sticker`, либо `webm_sticker`. " +#~ "Возвращает True в случае успешного " +#~ "добавления." + diff --git a/docs/source/locales/ru/LC_MESSAGES/types.po b/docs/source/locales/ru/LC_MESSAGES/types.po index db003a268..c846273fe 100644 --- a/docs/source/locales/ru/LC_MESSAGES/types.po +++ b/docs/source/locales/ru/LC_MESSAGES/types.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-02 19:24+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -23,9 +23,11 @@ msgid "Types of API" msgstr "" #: of telebot.types.Animation:1 telebot.types.Audio:1 -#: telebot.types.CallbackQuery:1 telebot.types.Chat:1 -#: telebot.types.ChatJoinRequest:1 telebot.types.ChatMember:1 -#: telebot.types.ChatMemberUpdated:1 telebot.types.ChatPhoto:1 +#: telebot.types.BotDescription:1 telebot.types.BotName:1 +#: telebot.types.BotShortDescription:1 telebot.types.CallbackQuery:1 +#: telebot.types.Chat:1 telebot.types.ChatJoinRequest:1 +#: telebot.types.ChatMember:1 telebot.types.ChatMemberUpdated:1 +#: telebot.types.ChatPhoto:1 telebot.types.ChatShared:1 #: telebot.types.ChosenInlineResult:1 telebot.types.Contact:1 #: telebot.types.Document:1 telebot.types.File:1 telebot.types.ForumTopic:1 #: telebot.types.ForumTopicClosed:1 telebot.types.ForumTopicCreated:1 @@ -41,8 +43,8 @@ msgstr "" #: telebot.types.ShippingQuery:1 telebot.types.Sticker:1 #: telebot.types.StickerSet:1 telebot.types.SuccessfulPayment:1 #: telebot.types.Update:1 telebot.types.UserProfilePhotos:1 -#: telebot.types.Venue:1 telebot.types.Video:1 telebot.types.VideoChatEnded:1 -#: telebot.types.VideoChatParticipantsInvited:1 +#: telebot.types.UserShared:1 telebot.types.Venue:1 telebot.types.Video:1 +#: telebot.types.VideoChatEnded:1 telebot.types.VideoChatParticipantsInvited:1 #: telebot.types.VideoChatScheduled:1 telebot.types.VideoChatStarted:1 #: telebot.types.VideoNote:1 telebot.types.Voice:1 telebot.types.WebhookInfo:1 #: telebot.types.WriteAccessAllowed:1 @@ -66,14 +68,16 @@ msgstr "" #: telebot.types.BotCommandScopeChat #: telebot.types.BotCommandScopeChatAdministrators #: telebot.types.BotCommandScopeChatMember telebot.types.BotCommandScopeDefault -#: telebot.types.CallbackQuery telebot.types.Chat -#: telebot.types.ChatAdministratorRights telebot.types.ChatInviteLink -#: telebot.types.ChatJoinRequest telebot.types.ChatLocation -#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned -#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember -#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted -#: telebot.types.ChatMemberUpdated telebot.types.ChatPermissions -#: telebot.types.ChatPhoto telebot.types.ChosenInlineResult +#: telebot.types.BotDescription telebot.types.BotName +#: telebot.types.BotShortDescription telebot.types.CallbackQuery +#: telebot.types.Chat telebot.types.ChatAdministratorRights +#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest +#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator +#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft +#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner +#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated +#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.ChatShared telebot.types.ChosenInlineResult #: telebot.types.Contact telebot.types.Dice telebot.types.Document #: telebot.types.File telebot.types.ForceReply telebot.types.ForumTopic #: telebot.types.ForumTopicCreated telebot.types.ForumTopicEdited @@ -95,15 +99,17 @@ msgstr "" #: telebot.types.InlineQueryResultGif telebot.types.InlineQueryResultLocation #: telebot.types.InlineQueryResultMpeg4Gif telebot.types.InlineQueryResultPhoto #: telebot.types.InlineQueryResultVenue telebot.types.InlineQueryResultVideo -#: telebot.types.InlineQueryResultVoice +#: telebot.types.InlineQueryResultVoice telebot.types.InlineQueryResultsButton #: telebot.types.InputContactMessageContent telebot.types.InputFile #: telebot.types.InputInvoiceMessageContent #: telebot.types.InputLocationMessageContent telebot.types.InputMediaAnimation #: telebot.types.InputMediaAudio telebot.types.InputMediaDocument #: telebot.types.InputMediaPhoto telebot.types.InputMediaVideo -#: telebot.types.InputTextMessageContent telebot.types.InputVenueMessageContent -#: telebot.types.Invoice telebot.types.KeyboardButton -#: telebot.types.KeyboardButtonPollType telebot.types.LabeledPrice +#: telebot.types.InputSticker telebot.types.InputTextMessageContent +#: telebot.types.InputVenueMessageContent telebot.types.Invoice +#: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType +#: telebot.types.KeyboardButtonRequestChat +#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice #: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message @@ -117,11 +123,13 @@ msgstr "" #: telebot.types.ShippingAddress telebot.types.ShippingOption #: telebot.types.ShippingOption.add_price telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet -#: telebot.types.SuccessfulPayment telebot.types.Update telebot.types.User -#: telebot.types.UserProfilePhotos telebot.types.Venue telebot.types.Video +#: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat +#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos +#: telebot.types.UserShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo +#: telebot.types.WriteAccessAllowed msgid "Parameters" msgstr "" @@ -183,14 +191,16 @@ msgstr "" #: telebot.types.BotCommandScopeChat #: telebot.types.BotCommandScopeChatAdministrators #: telebot.types.BotCommandScopeChatMember telebot.types.BotCommandScopeDefault -#: telebot.types.CallbackQuery telebot.types.Chat -#: telebot.types.ChatAdministratorRights telebot.types.ChatInviteLink -#: telebot.types.ChatJoinRequest telebot.types.ChatLocation -#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned -#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember -#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted -#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference -#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.BotDescription telebot.types.BotName +#: telebot.types.BotShortDescription telebot.types.CallbackQuery +#: telebot.types.Chat telebot.types.ChatAdministratorRights +#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest +#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator +#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft +#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner +#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated +#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions +#: telebot.types.ChatPhoto telebot.types.ChatShared #: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice #: telebot.types.Document telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game @@ -211,15 +221,17 @@ msgstr "" #: telebot.types.InlineQueryResultGif telebot.types.InlineQueryResultLocation #: telebot.types.InlineQueryResultMpeg4Gif telebot.types.InlineQueryResultPhoto #: telebot.types.InlineQueryResultVenue telebot.types.InlineQueryResultVideo -#: telebot.types.InlineQueryResultVoice +#: telebot.types.InlineQueryResultVoice telebot.types.InlineQueryResultsButton #: telebot.types.InputContactMessageContent #: telebot.types.InputInvoiceMessageContent #: telebot.types.InputLocationMessageContent telebot.types.InputMediaAnimation #: telebot.types.InputMediaAudio telebot.types.InputMediaDocument #: telebot.types.InputMediaPhoto telebot.types.InputMediaVideo -#: telebot.types.InputTextMessageContent telebot.types.InputVenueMessageContent -#: telebot.types.Invoice telebot.types.KeyboardButton -#: telebot.types.KeyboardButtonPollType telebot.types.LabeledPrice +#: telebot.types.InputSticker telebot.types.InputTextMessageContent +#: telebot.types.InputVenueMessageContent telebot.types.Invoice +#: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType +#: telebot.types.KeyboardButtonRequestChat +#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice #: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message @@ -232,8 +244,9 @@ msgstr "" #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingOption.add_price #: telebot.types.ShippingQuery telebot.types.Sticker telebot.types.StickerSet -#: telebot.types.SuccessfulPayment telebot.types.Update telebot.types.User -#: telebot.types.UserProfilePhotos telebot.types.Venue telebot.types.Video +#: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat +#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos +#: telebot.types.UserShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -248,20 +261,22 @@ msgstr "" #: telebot.types.BotCommandScopeChat:12 #: telebot.types.BotCommandScopeChatAdministrators:12 #: telebot.types.BotCommandScopeChatMember:15 -#: telebot.types.BotCommandScopeDefault:8 telebot.types.CallbackQuery:30 -#: telebot.types.Chat:109 telebot.types.ChatAdministratorRights:46 -#: telebot.types.ChatInviteLink:34 telebot.types.ChatJoinRequest:20 -#: telebot.types.ChatLocation:11 telebot.types.ChatMemberAdministrator:59 -#: telebot.types.ChatMemberBanned:15 telebot.types.ChatMemberLeft:11 -#: telebot.types.ChatMemberMember:11 telebot.types.ChatMemberOwner:17 -#: telebot.types.ChatMemberRestricted:47 telebot.types.ChatMemberUpdated:24 -#: telebot.types.ChatPermissions:38 telebot.types.ChatPhoto:21 +#: telebot.types.BotCommandScopeDefault:8 telebot.types.BotDescription:8 +#: telebot.types.BotName:8 telebot.types.BotShortDescription:8 +#: telebot.types.CallbackQuery:30 telebot.types.Chat:109 +#: telebot.types.ChatAdministratorRights:46 telebot.types.ChatInviteLink:34 +#: telebot.types.ChatJoinRequest:27 telebot.types.ChatLocation:11 +#: telebot.types.ChatMemberAdministrator:59 telebot.types.ChatMemberBanned:15 +#: telebot.types.ChatMemberLeft:11 telebot.types.ChatMemberMember:11 +#: telebot.types.ChatMemberOwner:17 telebot.types.ChatMemberRestricted:61 +#: telebot.types.ChatMemberUpdated:27 telebot.types.ChatPermissions:56 +#: telebot.types.ChatPhoto:21 telebot.types.ChatShared:15 #: telebot.types.ChosenInlineResult:21 telebot.types.Contact:22 #: telebot.types.Dice:11 telebot.types.Document:26 telebot.types.File:21 #: telebot.types.ForceReply:18 telebot.types.ForumTopic:17 #: telebot.types.ForumTopicCreated:14 telebot.types.Game:25 -#: telebot.types.GameHighScore:14 telebot.types.InlineKeyboardButton:45 -#: telebot.types.InlineKeyboardMarkup:22 telebot.types.InlineQuery:26 +#: telebot.types.GameHighScore:14 telebot.types.InlineKeyboardButton:49 +#: telebot.types.InlineKeyboardMarkup:28 telebot.types.InlineQuery:26 #: telebot.types.InlineQueryResultArticle:38 #: telebot.types.InlineQueryResultAudio:40 #: telebot.types.InlineQueryResultCachedAudio:31 @@ -281,31 +296,35 @@ msgstr "" #: telebot.types.InlineQueryResultVenue:51 #: telebot.types.InlineQueryResultVideo:53 #: telebot.types.InlineQueryResultVoice:37 +#: telebot.types.InlineQueryResultsButton:22 #: telebot.types.InputContactMessageContent:17 #: telebot.types.InputInvoiceMessageContent:75 #: telebot.types.InputLocationMessageContent:26 #: telebot.types.InputMediaAnimation:40 telebot.types.InputMediaAudio:37 #: telebot.types.InputMediaDocument:32 telebot.types.InputMediaPhoto:24 -#: telebot.types.InputMediaVideo:43 telebot.types.InputTextMessageContent:19 +#: telebot.types.InputMediaVideo:43 telebot.types.InputSticker:18 +#: telebot.types.InputTextMessageContent:19 #: telebot.types.InputVenueMessageContent:30 telebot.types.Invoice:22 -#: telebot.types.KeyboardButton:25 telebot.types.KeyboardButtonPollType:9 -#: telebot.types.LabeledPrice:13 telebot.types.Location:25 -#: telebot.types.LoginUrl:24 telebot.types.MaskPosition:20 -#: telebot.types.MenuButtonCommands:8 telebot.types.MenuButtonDefault:8 -#: telebot.types.MenuButtonWebApp:15 telebot.types.Message:246 -#: telebot.types.MessageAutoDeleteTimerChanged:8 telebot.types.MessageEntity:32 -#: telebot.types.MessageID:8 telebot.types.OrderInfo:17 -#: telebot.types.PhotoSize:21 telebot.types.Poll:47 telebot.types.PollAnswer:15 -#: telebot.types.PollOption:11 telebot.types.PreCheckoutQuery:28 -#: telebot.types.ProximityAlertTriggered:14 +#: telebot.types.KeyboardButton:33 telebot.types.KeyboardButtonPollType:9 +#: telebot.types.KeyboardButtonRequestChat:35 +#: telebot.types.KeyboardButtonRequestUser:18 telebot.types.LabeledPrice:13 +#: telebot.types.Location:25 telebot.types.LoginUrl:24 +#: telebot.types.MaskPosition:20 telebot.types.MenuButtonCommands:8 +#: telebot.types.MenuButtonDefault:8 telebot.types.MenuButtonWebApp:15 +#: telebot.types.Message:252 telebot.types.MessageAutoDeleteTimerChanged:8 +#: telebot.types.MessageEntity:32 telebot.types.MessageID:8 +#: telebot.types.OrderInfo:17 telebot.types.PhotoSize:21 telebot.types.Poll:47 +#: telebot.types.PollAnswer:15 telebot.types.PollOption:11 +#: telebot.types.PreCheckoutQuery:28 telebot.types.ProximityAlertTriggered:14 #: telebot.types.ReplyKeyboardMarkup:49 telebot.types.ReplyKeyboardRemove:18 #: telebot.types.SentWebAppMessage:9 telebot.types.ShippingAddress:23 #: telebot.types.ShippingOption:14 telebot.types.ShippingQuery:17 -#: telebot.types.Sticker:49 telebot.types.StickerSet:30 -#: telebot.types.SuccessfulPayment:28 telebot.types.Update:61 +#: telebot.types.Sticker:54 telebot.types.StickerSet:30 +#: telebot.types.SuccessfulPayment:28 +#: telebot.types.SwitchInlineQueryChosenChat:22 telebot.types.Update:61 #: telebot.types.User:41 telebot.types.UserProfilePhotos:11 -#: telebot.types.Venue:27 telebot.types.Video:35 telebot.types.VideoChatEnded:8 -#: telebot.types.VideoChatParticipantsInvited:8 +#: telebot.types.UserShared:15 telebot.types.Venue:27 telebot.types.Video:35 +#: telebot.types.VideoChatEnded:8 telebot.types.VideoChatParticipantsInvited:8 #: telebot.types.VideoChatScheduled:9 telebot.types.VideoNote:24 #: telebot.types.Voice:23 telebot.types.WebAppData:12 #: telebot.types.WebAppInfo:8 telebot.types.WebhookInfo:37 @@ -320,14 +339,16 @@ msgstr "" #: telebot.types.BotCommandScopeChat #: telebot.types.BotCommandScopeChatAdministrators #: telebot.types.BotCommandScopeChatMember telebot.types.BotCommandScopeDefault -#: telebot.types.CallbackQuery telebot.types.Chat -#: telebot.types.ChatAdministratorRights telebot.types.ChatInviteLink -#: telebot.types.ChatJoinRequest telebot.types.ChatLocation -#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned -#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember -#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted -#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference -#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.BotDescription telebot.types.BotName +#: telebot.types.BotShortDescription telebot.types.CallbackQuery +#: telebot.types.Chat telebot.types.ChatAdministratorRights +#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest +#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator +#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft +#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner +#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated +#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions +#: telebot.types.ChatPhoto telebot.types.ChatShared #: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice #: telebot.types.Document telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game @@ -348,15 +369,17 @@ msgstr "" #: telebot.types.InlineQueryResultGif telebot.types.InlineQueryResultLocation #: telebot.types.InlineQueryResultMpeg4Gif telebot.types.InlineQueryResultPhoto #: telebot.types.InlineQueryResultVenue telebot.types.InlineQueryResultVideo -#: telebot.types.InlineQueryResultVoice +#: telebot.types.InlineQueryResultVoice telebot.types.InlineQueryResultsButton #: telebot.types.InputContactMessageContent #: telebot.types.InputInvoiceMessageContent #: telebot.types.InputLocationMessageContent telebot.types.InputMediaAnimation #: telebot.types.InputMediaAudio telebot.types.InputMediaDocument #: telebot.types.InputMediaPhoto telebot.types.InputMediaVideo -#: telebot.types.InputTextMessageContent telebot.types.InputVenueMessageContent -#: telebot.types.Invoice telebot.types.KeyboardButton -#: telebot.types.KeyboardButtonPollType telebot.types.LabeledPrice +#: telebot.types.InputSticker telebot.types.InputTextMessageContent +#: telebot.types.InputVenueMessageContent telebot.types.Invoice +#: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType +#: telebot.types.KeyboardButtonRequestChat +#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice #: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message @@ -369,8 +392,9 @@ msgstr "" #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet -#: telebot.types.SuccessfulPayment telebot.types.Update telebot.types.User -#: telebot.types.UserProfilePhotos telebot.types.Venue telebot.types.Video +#: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat +#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos +#: telebot.types.UserShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -703,6 +727,56 @@ msgstr "" msgid ":class:`telebot.types.BotCommandScopeDefault`" msgstr "" +#: of telebot.types.BotDescription:1 +msgid "This object represents a bot description." +msgstr "" + +#: of telebot.types.BotDescription:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#botdescription" +msgstr "" + +#: of telebot.types.BotDescription:5 +msgid "Bot description" +msgstr "" + +#: of telebot.types.BotDescription:9 +msgid ":class:`telebot.types.BotDescription`" +msgstr "" + +#: of telebot.types.BotName:1 +msgid "This object represents a bot name." +msgstr "" + +#: of telebot.types.BotName:3 +msgid "Telegram Documentation: https://core.telegram.org/bots/api#botname" +msgstr "" + +#: of telebot.types.BotName:5 +msgid "The bot name" +msgstr "" + +#: of telebot.types.BotName:9 +msgid ":class:`BotName`" +msgstr "" + +#: of telebot.types.BotShortDescription:1 +msgid "This object represents a bot short description." +msgstr "" + +#: of telebot.types.BotShortDescription:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#botshortdescription" +msgstr "" + +#: of telebot.types.BotShortDescription:5 +msgid "Bot short description" +msgstr "" + +#: of telebot.types.BotShortDescription:9 +msgid ":class:`telebot.types.BotShortDescription`" +msgstr "" + #: of telebot.types.CallbackQuery:1 msgid "" "This object represents an incoming callback query from a callback button " @@ -1120,20 +1194,31 @@ msgid "User that sent the join request" msgstr "" #: of telebot.types.ChatJoinRequest:11 +msgid "" +"Optional. Identifier of a private chat with the user who sent the join " +"request. This number may have more than 32 significant bits and some " +"programming languages may have difficulty/silent defects in interpreting " +"it. But it has at most 52 significant bits, so a 64-bit integer or " +"double-precision float type are safe for storing this identifier. The bot" +" can use this identifier for 24 hours to send messages until the join " +"request is processed, assuming no other administrator contacted the user." +msgstr "" + +#: of telebot.types.ChatJoinRequest:18 msgid "Date the request was sent in Unix time" msgstr "" -#: of telebot.types.ChatJoinRequest:14 +#: of telebot.types.ChatJoinRequest:21 msgid "Optional. Bio of the user." msgstr "" -#: of telebot.types.ChatJoinRequest:17 +#: of telebot.types.ChatJoinRequest:24 msgid "" "Optional. Chat invite link that was used by the user to send the join " "request" msgstr "" -#: of telebot.types.ChatJoinRequest:21 +#: of telebot.types.ChatJoinRequest:28 msgid ":class:`telebot.types.ChatJoinRequest`" msgstr "" @@ -1177,7 +1262,7 @@ msgstr "" msgid ":class:`telebot.types.ChatMemberMember`" msgstr "" -#: of telebot.types.ChatMember:7 telebot.types.ChatMemberRestricted:48 +#: of telebot.types.ChatMember:7 telebot.types.ChatMemberRestricted:62 msgid ":class:`telebot.types.ChatMemberRestricted`" msgstr "" @@ -1328,26 +1413,44 @@ msgid "" msgstr "" #: of telebot.types.ChatMemberRestricted:29 -msgid "" -"True, if the user is allowed to send audios, documents, photos, videos, " -"video notes and voice notes" +msgid "True, if the user is allowed to send audios" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:32 +msgid "True, if the user is allowed to send documents" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:35 +msgid "True, if the user is allowed to send photos" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:38 +msgid "True, if the user is allowed to send videos" msgstr "" -#: of telebot.types.ChatMemberRestricted:33 +#: of telebot.types.ChatMemberRestricted:41 +msgid "True, if the user is allowed to send video notes" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:44 +msgid "True, if the user is allowed to send voice notes" +msgstr "" + +#: of telebot.types.ChatMemberRestricted:47 msgid "True, if the user is allowed to send polls" msgstr "" -#: of telebot.types.ChatMemberRestricted:36 +#: of telebot.types.ChatMemberRestricted:50 msgid "" "True, if the user is allowed to send animations, games, stickers and use " "inline bots" msgstr "" -#: of telebot.types.ChatMemberRestricted:40 +#: of telebot.types.ChatMemberRestricted:54 msgid "True, if the user is allowed to add web page previews to their messages" msgstr "" -#: of telebot.types.ChatMemberRestricted:43 +#: of telebot.types.ChatMemberRestricted:57 msgid "" "Date when restrictions will be lifted for this user; unix time. If 0, " "then the user is restricted forever" @@ -1389,7 +1492,11 @@ msgid "" "for joining by invite link events only." msgstr "" -#: of telebot.types.ChatMemberUpdated:25 +#: of telebot.types.ChatMemberUpdated:24 +msgid "Optional. True, if the user joined the chat via a chat folder invite link" +msgstr "" + +#: of telebot.types.ChatMemberUpdated:28 msgid ":class:`telebot.types.ChatMemberUpdated`" msgstr "" @@ -1421,52 +1528,76 @@ msgid "" msgstr "" #: of telebot.types.ChatPermissions:9 -msgid "" -"Optional. True, if the user is allowed to send audios, documents, photos," -" videos, video notes and voice notes, implies can_send_messages" +msgid "Optional. True, if the user is allowed to send audios" msgstr "" -#: of telebot.types.ChatPermissions:13 +#: of telebot.types.ChatPermissions:12 +msgid "Optional. True, if the user is allowed to send documents" +msgstr "" + +#: of telebot.types.ChatPermissions:15 +msgid "Optional. True, if the user is allowed to send photos" +msgstr "" + +#: of telebot.types.ChatPermissions:18 +msgid "Optional. True, if the user is allowed to send videos" +msgstr "" + +#: of telebot.types.ChatPermissions:21 +msgid "Optional. True, if the user is allowed to send video notes" +msgstr "" + +#: of telebot.types.ChatPermissions:24 +msgid "Optional. True, if the user is allowed to send voice notes" +msgstr "" + +#: of telebot.types.ChatPermissions:27 msgid "" "Optional. True, if the user is allowed to send polls, implies " "can_send_messages" msgstr "" -#: of telebot.types.ChatPermissions:16 +#: of telebot.types.ChatPermissions:30 msgid "" "Optional. True, if the user is allowed to send animations, games, " -"stickers and use inline bots, implies can_send_media_messages" +"stickers and use inline bots" msgstr "" -#: of telebot.types.ChatPermissions:20 +#: of telebot.types.ChatPermissions:34 msgid "" "Optional. True, if the user is allowed to add web page previews to their " -"messages, implies can_send_media_messages" +"messages" msgstr "" -#: of telebot.types.ChatPermissions:24 +#: of telebot.types.ChatPermissions:38 msgid "" "Optional. True, if the user is allowed to change the chat title, photo " "and other settings. Ignored in public supergroups" msgstr "" -#: of telebot.types.ChatPermissions:28 +#: of telebot.types.ChatPermissions:42 msgid "Optional. True, if the user is allowed to invite new users to the chat" msgstr "" -#: of telebot.types.ChatPermissions:31 +#: of telebot.types.ChatPermissions:45 msgid "" "Optional. True, if the user is allowed to pin messages. Ignored in public" " supergroups" msgstr "" -#: of telebot.types.ChatPermissions:34 +#: of telebot.types.ChatPermissions:48 msgid "" "Optional. True, if the user is allowed to create forum topics. If omitted" " defaults to the value of can_pin_messages" msgstr "" -#: of telebot.types.ChatPermissions:39 +#: of telebot.types.ChatPermissions:52 +msgid "" +"deprecated. True, if the user is allowed to send audios, documents, " +"photos, videos, video notes and voice notes" +msgstr "" + +#: of telebot.types.ChatPermissions:57 msgid ":class:`telebot.types.ChatPermissions`" msgstr "" @@ -1508,6 +1639,36 @@ msgstr "" msgid ":class:`telebot.types.ChatPhoto`" msgstr "" +#: of telebot.types.ChatShared:1 +msgid "" +"This object contains information about the chat whose identifier was " +"shared with the bot using a `telebot.types.KeyboardButtonRequestChat` " +"button." +msgstr "" + +#: of telebot.types.ChatShared:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#Chatshared" +msgstr "" + +#: of telebot.types.ChatShared:6 telebot.types.UserShared:6 +msgid "identifier of the request" +msgstr "" + +#: of telebot.types.ChatShared:9 +msgid "" +"Identifier of the shared chat. This number may have more than 32 " +"significant bits and some programming languages may have " +"difficulty/silent defects in interpreting it. But it has at most 52 " +"significant bits, so a 64-bit integer or double-precision float type are " +"safe for storing this identifier. The bot may not have access to the chat" +" and could be unable to use this identifier, unless the chat is already " +"known to the bot by some other means." +msgstr "" + +#: of telebot.types.ChatShared:16 +msgid ":class:`telebot.types.ChatShared`" +msgstr "" + #: of telebot.types.ChosenInlineResult:1 msgid "" "Represents a result of an inline query that was chosen by the user and " @@ -1915,12 +2076,14 @@ msgid "" msgstr "" #: of telebot.types.InlineKeyboardButton:3 +#: telebot.types.SwitchInlineQueryChosenChat:4 msgid "" "Telegram Documentation: " "https://core.telegram.org/bots/api#inlinekeyboardbutton" msgstr "" #: of telebot.types.InlineKeyboardButton:5 +#: telebot.types.InlineQueryResultsButton:6 msgid "Label text on the button" msgstr "" @@ -1974,19 +2137,26 @@ msgstr "" #: of telebot.types.InlineKeyboardButton:37 msgid "" +"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 query in the input field" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:41 +msgid "" "Optional. Description of the game that will be launched when the user " "presses the button. NOTE: This type of button must always be the first " "button in the first row." msgstr "" -#: of telebot.types.InlineKeyboardButton:41 +#: of telebot.types.InlineKeyboardButton:45 msgid "" "Optional. Specify True, to send a Pay button. NOTE: This type of button " "must always be the first button in the first row and can only be used in " "invoice messages." msgstr "" -#: of telebot.types.InlineKeyboardButton:46 +#: of telebot.types.InlineKeyboardButton:50 msgid ":class:`telebot.types.InlineKeyboardButton`" msgstr "" @@ -2004,19 +2174,23 @@ msgstr "" msgid "Example of a custom keyboard with buttons." msgstr "" -#: of telebot.types.InlineKeyboardMarkup:16 +#: of telebot.types.InlineKeyboardMarkup:19 msgid "" "Telegram Documentation: " "https://core.telegram.org/bots/api#inlinekeyboardmarkup" msgstr "" -#: of telebot.types.InlineKeyboardMarkup:18 +#: of telebot.types.InlineKeyboardMarkup:21 msgid "" ":obj:`list` of button rows, each represented by an :obj:`list` of " ":class:`telebot.types.InlineKeyboardButton` objects" msgstr "" -#: of telebot.types.InlineKeyboardMarkup:23 +#: of telebot.types.InlineKeyboardMarkup:25 +msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row" +msgstr "" + +#: of telebot.types.InlineKeyboardMarkup:29 #: telebot.types.InlineKeyboardMarkup.add:17 #: telebot.types.InlineKeyboardMarkup.row:12 msgid ":class:`telebot.types.InlineKeyboardMarkup`" @@ -3165,12 +3339,58 @@ msgstr "" msgid ":class:`telebot.types.InlineQueryResultVoice`" msgstr "" +#: of telebot.types.InlineQueryResultsButton:1 telebot.types.LabeledPrice:1 +msgid "" +"Bases: :py:class:`telebot.types.JsonSerializable`, " +":py:class:`telebot.types.Dictionaryable`" +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:1 +msgid "" +"This object represents a button to be shown above inline query results. " +"You must use exactly one of the optional fields." +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#inlinequeryresultsbutton" +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:9 +msgid "" +"Optional. Description of the Web App that will be launched when the user " +"presses the button. The Web App will be able to switch back to the inline" +" mode using the method web_app_switch_inline_query inside the Web App." +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:13 +msgid "" +"Optional. Deep-linking parameter for the /start message sent to the bot " +"when a user presses the button. 1-64 characters, only A-Z, a-z, 0-9, _ " +"and - are allowed. Example: An inline bot that sends YouTube videos can " +"ask the user to connect the bot to their YouTube account to adapt search " +"results accordingly. To do this, it displays a 'Connect your YouTube " +"account' button above the results, or even before showing any. The user " +"presses the button, switches to a private chat with the bot and, in doing" +" so, passes a start parameter that instructs the bot to return an OAuth " +"link. Once done, the bot can offer a switch_inline button so that the " +"user can easily return to the chat where they wanted to use the bot's " +"inline capabilities." +msgstr "" + +#: of telebot.types.InlineQueryResultsButton:23 +msgid ":class:`InlineQueryResultsButton`" +msgstr "" + #: of telebot.types.InputContactMessageContent:1 #: telebot.types.InputInvoiceMessageContent:1 #: telebot.types.InputLocationMessageContent:1 #: telebot.types.InputTextMessageContent:1 #: telebot.types.InputVenueMessageContent:1 #: telebot.types.KeyboardButtonPollType:1 +#: telebot.types.KeyboardButtonRequestChat:1 +#: telebot.types.KeyboardButtonRequestUser:1 msgid "Bases: :py:class:`telebot.types.Dictionaryable`" msgstr "" @@ -3367,7 +3587,8 @@ msgstr "" msgid ":class:`telebot.types.InputLocationMessageContent`" msgstr "" -#: of telebot.types.InputMedia:1 telebot.types.KeyboardButton:1 +#: of telebot.types.InputMedia:1 telebot.types.InputSticker:1 +#: telebot.types.KeyboardButton:1 msgid "" "Bases: :py:class:`telebot.types.Dictionaryable`, " ":py:class:`telebot.types.JsonSerializable`" @@ -3560,6 +3781,39 @@ msgstr "" msgid ":class:`telebot.types.InputMediaVideo`" msgstr "" +#: of telebot.types.InputSticker:1 +msgid "This object describes a sticker to be added to a sticker set." +msgstr "" + +#: of telebot.types.InputSticker:3 +msgid "" +"The added sticker. Pass a file_id as a String to send a file that already" +" exists on the Telegram servers, pass an HTTP URL as a String for " +"Telegram to get a file from the Internet, or upload a new one using " +"multipart/form-data. Animated and video stickers can't be uploaded via " +"HTTP URL." +msgstr "" + +#: of telebot.types.InputSticker:8 +msgid "One or more(up to 20) emoji(s) corresponding to the sticker" +msgstr "" + +#: of telebot.types.InputSticker:11 +msgid "" +"Optional. Position where the mask should be placed on faces. For “mask” " +"stickers only." +msgstr "" + +#: of telebot.types.InputSticker:14 +msgid "" +"Optional. List of 0-20 search keywords for the sticker with total length " +"of up to 64 characters. For “regular” and “custom_emoji” stickers only." +msgstr "" + +#: of telebot.types.InputSticker:19 +msgid ":class:`telebot.types.InputSticker`" +msgstr "" + #: of telebot.types.InputTextMessageContent:1 msgid "" "Represents the content of a text message to be sent as the result of an " @@ -3726,7 +3980,21 @@ msgid "" "service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:26 +#: of telebot.types.KeyboardButton:25 +msgid "" +"Optional. If specified, pressing the button will open a list of suitable " +"users. Tapping on any user will send their identifier to the bot in a " +"“user_shared” service message. Available in private chats only." +msgstr "" + +#: of telebot.types.KeyboardButton:29 +msgid "" +"Optional. If specified, pressing the button will open a list of suitable " +"chats. Tapping on a chat will send its identifier to the bot in a " +"“chat_shared” service message. Available in private chats only." +msgstr "" + +#: of telebot.types.KeyboardButton:34 msgid ":class:`telebot.types.KeyboardButton`" msgstr "" @@ -3754,10 +4022,111 @@ msgstr "" msgid ":class:`telebot.types.KeyboardButtonPollType`" msgstr "" -#: of telebot.types.LabeledPrice:1 +#: of telebot.types.KeyboardButtonRequestChat:1 msgid "" -"Bases: :py:class:`telebot.types.JsonSerializable`, " -":py:class:`telebot.types.Dictionaryable`" +"This object defines the criteria used to request a suitable chat. The " +"identifier of the selected chat will be shared with the bot when the " +"corresponding button is pressed." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#keyboardbuttonrequestchat" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:6 +msgid "" +"Signed 32-bit identifier of the request, which will be received back in " +"the ChatShared object. Must be unique within the message" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:10 +msgid "" +"Pass True to request a channel chat, pass False to request a group or a " +"supergroup chat." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:13 +msgid "" +"Optional. Pass True to request a forum supergroup, pass False to request " +"a non-forum chat. If not specified, no additional restrictions are " +"applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:17 +msgid "" +"Optional. Pass True to request a supergroup or a channel with a username," +" pass False to request a chat without a username. If not specified, no " +"additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:21 +msgid "" +"Optional. Pass True to request a chat owned by the user. Otherwise, no " +"additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:24 +msgid "" +"Optional. A JSON-serialized object listing the required administrator " +"rights of the user in the chat. The rights must be a superset of " +"bot_administrator_rights. If not specified, no additional restrictions " +"are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:28 +msgid "" +"Optional. A JSON-serialized object listing the required administrator " +"rights of the bot in the chat. The rights must be a subset of " +"user_administrator_rights. If not specified, no additional restrictions " +"are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:32 +msgid "" +"Optional. Pass True to request a chat where the bot is a member. " +"Otherwise, no additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestChat:36 +msgid ":class:`telebot.types.KeyboardButtonRequestChat`" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:1 +msgid "" +"This object defines the criteria used to request a suitable user. The " +"identifier of the selected user will be shared with the bot when the " +"corresponding button is pressed." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#keyboardbuttonrequestuser" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:6 +msgid "" +"Signed 32-bit identifier of the request, which will be received back in " +"the UserShared object. Must be unique within the message" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:10 +msgid "" +"Optional. Pass True to request a bot, pass False to request a regular " +"user. If not specified, no additional restrictions are applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:14 +msgid "" +"Optional. Pass True to request a premium user, pass False to request a " +"non-premium user. If not specified, no additional restrictions are " +"applied." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:19 +msgid ":class:`telebot.types.KeyboardButtonRequestUser`" msgstr "" #: of telebot.types.LabeledPrice:1 @@ -4306,78 +4675,86 @@ msgid "" msgstr "" #: of telebot.types.Message:194 +msgid "Optional. Service message: a user was shared with the bot" +msgstr "" + +#: of telebot.types.Message:197 +msgid "Optional. Service message: a chat was shared with the bot" +msgstr "" + +#: of telebot.types.Message:200 msgid "" "Optional. The domain name of the website on which the user has logged in." " More about Telegram Login »" msgstr "" -#: of telebot.types.Message:198 +#: of telebot.types.Message:204 msgid "" "Optional. Service message: the user allowed the bot added to the " "attachment menu to write messages" msgstr "" -#: of telebot.types.Message:202 +#: of telebot.types.Message:208 msgid "Optional. Telegram Passport data" msgstr "" -#: of telebot.types.Message:205 +#: of telebot.types.Message:211 msgid "" "Optional. Service message. A user in the chat triggered another user's " "proximity alert while sharing Live Location." msgstr "" -#: of telebot.types.Message:209 +#: of telebot.types.Message:215 msgid "Optional. Service message: forum topic created" msgstr "" -#: of telebot.types.Message:212 +#: of telebot.types.Message:218 msgid "Optional. Service message: forum topic edited" msgstr "" -#: of telebot.types.Message:215 +#: of telebot.types.Message:221 msgid "Optional. Service message: forum topic closed" msgstr "" -#: of telebot.types.Message:218 +#: of telebot.types.Message:224 msgid "Optional. Service message: forum topic reopened" msgstr "" -#: of telebot.types.Message:221 +#: of telebot.types.Message:227 msgid "Optional. Service message: the 'General' forum topic hidden" msgstr "" -#: of telebot.types.Message:224 +#: of telebot.types.Message:230 msgid "Optional. Service message: the 'General' forum topic unhidden" msgstr "" -#: of telebot.types.Message:227 +#: of telebot.types.Message:233 msgid "Optional. Service message: video chat scheduled" msgstr "" -#: of telebot.types.Message:230 +#: of telebot.types.Message:236 msgid "Optional. Service message: video chat started" msgstr "" -#: of telebot.types.Message:233 +#: of telebot.types.Message:239 msgid "Optional. Service message: video chat ended" msgstr "" -#: of telebot.types.Message:236 +#: of telebot.types.Message:242 msgid "Optional. Service message: new participants invited to a video chat" msgstr "" -#: of telebot.types.Message:239 +#: of telebot.types.Message:245 msgid "Optional. Service message: data sent by a Web App" msgstr "" -#: of telebot.types.Message:242 +#: of telebot.types.Message:248 msgid "" "Optional. Inline keyboard attached to the message. login_url buttons are " "represented as ordinary url buttons." msgstr "" -#: of telebot.types.Message:247 +#: of telebot.types.Message:253 msgid ":class:`telebot.types.Message`" msgstr "" @@ -4540,7 +4917,7 @@ msgstr "" msgid "Photo height" msgstr "" -#: of telebot.types.PhotoSize:18 telebot.types.Sticker:46 +#: of telebot.types.PhotoSize:18 telebot.types.Sticker:51 #: telebot.types.VideoNote:21 msgid "Optional. File size in bytes" msgstr "" @@ -5058,7 +5435,14 @@ msgstr "" msgid "Optional. For custom emoji stickers, unique identifier of the custom emoji" msgstr "" -#: of telebot.types.Sticker:50 +#: of telebot.types.Sticker:46 +msgid "" +"Optional. True, if the sticker must be repainted to a text color in " +"messages, the color of the Telegram Premium badge in emoji status, white " +"color on chat photos, or another appropriate color in other places" +msgstr "" + +#: of telebot.types.Sticker:55 msgid ":class:`telebot.types.Sticker`" msgstr "" @@ -5136,6 +5520,45 @@ msgstr "" msgid ":class:`telebot.types.SuccessfulPayment`" msgstr "" +#: of telebot.types.SwitchInlineQueryChosenChat:1 telebot.types.User:1 +msgid "" +"Bases: :py:class:`telebot.types.JsonDeserializable`, " +":py:class:`telebot.types.Dictionaryable`, " +":py:class:`telebot.types.JsonSerializable`" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:1 +msgid "" +"Represents an inline button that switches the current user to inline mode" +" in a chosen chat, with an optional default inline query." +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:6 +msgid "" +"Optional. The default inline query to be inserted in the input field. If " +"left empty, only the bot's username will be inserted" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:10 +msgid "Optional. True, if private chats with users can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:13 +msgid "Optional. True, if private chats with bots can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:16 +msgid "Optional. True, if group and supergroup chats can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:19 +msgid "Optional. True, if channel chats can be chosen" +msgstr "" + +#: of telebot.types.SwitchInlineQueryChosenChat:23 +msgid ":class:`SwitchInlineQueryChosenChat`" +msgstr "" + #: of telebot.types.Update:1 msgid "" "This object represents an incoming update.At most one of the optional " @@ -5240,13 +5663,6 @@ msgstr "" msgid ":class:`telebot.types.Update`" msgstr "" -#: of telebot.types.User:1 -msgid "" -"Bases: :py:class:`telebot.types.JsonDeserializable`, " -":py:class:`telebot.types.Dictionaryable`, " -":py:class:`telebot.types.JsonSerializable`" -msgstr "" - #: of telebot.types.User:1 msgid "This object represents a Telegram user or bot." msgstr "" @@ -5348,6 +5764,32 @@ msgstr "" msgid ":class:`telebot.types.UserProfilePhotos`" msgstr "" +#: of telebot.types.UserShared:1 +msgid "" +"This object contains information about the user whose identifier was " +"shared with the bot using a `telebot.types.KeyboardButtonRequestUser` " +"button." +msgstr "" + +#: of telebot.types.UserShared:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#usershared" +msgstr "" + +#: of telebot.types.UserShared:9 +msgid "" +"Identifier of the shared user. This number may have more than 32 " +"significant bits and some programming languages may have " +"difficulty/silent defects in interpreting it. But it has at most 52 " +"significant bits, so a 64-bit integer or double-precision float type are " +"safe for storing this identifier. The bot may not have access to the user" +" and could be unable to use this identifier, unless the user is already " +"known to the bot by some other means." +msgstr "" + +#: of telebot.types.UserShared:16 +msgid ":class:`telebot.types.UserShared`" +msgstr "" + #: of telebot.types.Venue:1 msgid "This object represents a venue." msgstr "" @@ -5633,6 +6075,37 @@ msgid "" "https://core.telegram.org/bots/api#writeaccessallowed" msgstr "" +#: of telebot.types.WriteAccessAllowed:6 +msgid "Optional. Name of the Web App which was launched from a link" +msgstr "" + #~ msgid "Type of the result, must be animation" #~ msgstr "" +#~ msgid "" +#~ "True, if the user is allowed to" +#~ " send audios, documents, photos, videos," +#~ " video notes and voice notes" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. True, if the user is " +#~ "allowed to send audios, documents, " +#~ "photos, videos, video notes and voice" +#~ " notes, implies can_send_messages" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. True, if the user is " +#~ "allowed to send animations, games, " +#~ "stickers and use inline bots, implies" +#~ " can_send_media_messages" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. True, if the user is " +#~ "allowed to add web page previews " +#~ "to their messages, implies " +#~ "can_send_media_messages" +#~ msgstr "" + diff --git a/docs/source/locales/ru/LC_MESSAGES/util.po b/docs/source/locales/ru/LC_MESSAGES/util.po index 0f3c4957b..1ba54df52 100644 --- a/docs/source/locales/ru/LC_MESSAGES/util.po +++ b/docs/source/locales/ru/LC_MESSAGES/util.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-29 14:44+0400\n" +"POT-Creation-Date: 2023-07-08 23:07+0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,19 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.9.1\n" -#: ../../util.rst:3 +#: ../../source/util.rst:3 msgid "Utils" msgstr "Утилиты" -#: ../../util.rst:5 +#: ../../source/util.rst:5 msgid "Utils in pyTelegramBotAPI" msgstr "Утилиты в pyTelegramBotAPI" -#: ../../util.rst:5 +#: ../../source/util.rst:5 msgid "ptba, pytba, pyTelegramBotAPI, utils, guide" msgstr "ptba, pytba, pyTelegramBotAPI, утилиты, гайд" -#: ../../util.rst:11 +#: ../../source/util.rst:11 msgid "util file" msgstr "Файл util" @@ -38,11 +38,14 @@ msgstr "Файл util" msgid "" "Use this function inside loops in order to avoid getting TooManyRequests " "error. Example:" -msgstr "Используйте эту функцию в циклах, чтобы избежать ошибки TooManyRequests. Пример:" +msgstr "" +"Используйте эту функцию в циклах, чтобы избежать ошибки TooManyRequests. " +"Пример:" -#: of telebot.util.antiflood telebot.util.escape telebot.util.extract_arguments -#: telebot.util.extract_command telebot.util.is_bytes telebot.util.is_command -#: telebot.util.is_dict telebot.util.is_pil_image +#: of telebot.service_utils.is_bytes telebot.service_utils.is_dict +#: telebot.service_utils.is_pil_image telebot.util.antiflood +#: telebot.util.escape telebot.util.extract_arguments +#: telebot.util.extract_command telebot.util.is_command #: telebot.util.parse_web_app_data telebot.util.quick_markup #: telebot.util.smart_split telebot.util.split_string telebot.util.user_link #: telebot.util.validate_web_app_data telebot.util.webhook_google_functions @@ -54,28 +57,33 @@ msgid "The function to call" msgstr "Вызываемая функция" #: of telebot.util.antiflood:13 +msgid "Number of retries to send" +msgstr "" + +#: of telebot.util.antiflood:16 msgid "The arguments to pass to the function" msgstr "Аргументы, для передачи в функцию" -#: of telebot.util.antiflood:16 +#: of telebot.util.antiflood:19 msgid "The keyword arguments to pass to the function" msgstr "Именованные аргументы для передачи в функцию" -#: of telebot.util.antiflood telebot.util.escape telebot.util.extract_arguments -#: telebot.util.extract_command telebot.util.generate_random_token -#: telebot.util.is_bytes telebot.util.is_command telebot.util.is_dict -#: telebot.util.is_pil_image telebot.util.parse_web_app_data -#: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string -#: telebot.util.user_link telebot.util.validate_web_app_data -#: telebot.util.webhook_google_functions +#: of telebot.service_utils.generate_random_token +#: telebot.service_utils.is_bytes telebot.service_utils.is_dict +#: telebot.service_utils.is_pil_image telebot.util.antiflood +#: telebot.util.escape telebot.util.extract_arguments +#: telebot.util.extract_command telebot.util.is_command +#: telebot.util.parse_web_app_data telebot.util.quick_markup +#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link +#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions msgid "Returns" msgstr "" -#: of telebot.util.antiflood:19 +#: of telebot.util.antiflood:22 msgid "None" msgstr "" -#: of telebot.util.chunks:1 +#: of telebot.service_utils.chunks:1 msgid "Yield successive n-sized chunks from lst." msgstr "Генерирует последовательные части списка, состоящие из n элементов." @@ -91,8 +99,9 @@ msgstr "Содержит все виды сервисных сообщений, msgid "" "Replaces the following chars in `text` ('&' with '&', '<' with '<'" " and '>' with '>')." -msgstr "Заменяет следующие символы в `text` ('&' на '&', '<' на '<'" -" и '>' на '>')." +msgstr "" +"Заменяет следующие символы в `text` ('&' на '&', '<' на '<' и '>' " +"на '>')." #: of telebot.util.escape:3 msgid "the text to escape" @@ -116,11 +125,14 @@ msgstr "Строка для извлечения аргументов коман #: of telebot.util.extract_arguments:13 msgid "the arguments if `text` is a command (according to is_command), else None." -msgstr "Аргументы, если `text` является командой (согласно is_command), в остальных случаях None." +msgstr "" +"Аргументы, если `text` является командой (согласно is_command), в " +"остальных случаях None." -#: of telebot.util.extract_arguments telebot.util.extract_command -#: telebot.util.generate_random_token telebot.util.is_bytes -#: telebot.util.is_command telebot.util.is_dict telebot.util.is_pil_image +#: of telebot.service_utils.generate_random_token +#: telebot.service_utils.is_bytes telebot.service_utils.is_dict +#: telebot.service_utils.is_pil_image telebot.util.extract_arguments +#: telebot.util.extract_command telebot.util.is_command #: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string #: telebot.util.user_link msgid "Return type" @@ -135,8 +147,9 @@ msgid "" "Extracts the command from `text` (minus the '/') if `text` is a command " "(see is_command). If `text` is not a command, this function returns None." msgstr "" -"Извлекает команду из `text` (исключает '/') если `text` является командой " -"(см. is_command). Если `text` не является командой, эта функция возвращает None." +"Извлекает команду из `text` (исключает '/') если `text` является командой" +" (см. is_command). Если `text` не является командой, эта функция " +"возвращает None." #: of telebot.util.extract_command:12 msgid "String to extract the command from" @@ -144,37 +157,41 @@ msgstr "Строка, из которой нужно извлечь команд #: of telebot.util.extract_command:15 msgid "the command if `text` is a command (according to is_command), else None." -msgstr "Команда, если `text` является командой (согласно is_command), в остальных случаях None." +msgstr "" +"Команда, если `text` является командой (согласно is_command), в остальных" +" случаях None." -#: of telebot.util.generate_random_token:1 +#: of telebot.service_utils.generate_random_token:1 msgid "" "Generates a random token consisting of letters and digits, 16 characters " "long." -msgstr "Генерирует рандомный токен, состоящий из латинских букв и цифр длиной 16 символов." +msgstr "" +"Генерирует рандомный токен, состоящий из латинских букв и цифр длиной 16 " +"символов." -#: of telebot.util.generate_random_token:3 +#: of telebot.service_utils.generate_random_token:3 msgid "a random token" msgstr "Сгенерированный токен" -#: of telebot.util.generate_random_token:4 telebot.util.user_link:22 +#: of telebot.service_utils.generate_random_token:4 telebot.util.user_link:22 msgid ":obj:`str`" msgstr "" -#: of telebot.util.is_bytes:1 +#: of telebot.service_utils.is_bytes:1 msgid "Returns True if the given object is a bytes object." msgstr "Возвращает True если полученный объект является bytes." -#: of telebot.util.is_bytes:3 telebot.util.is_dict:3 -#: telebot.util.is_pil_image:3 +#: of telebot.service_utils.is_bytes:3 telebot.service_utils.is_dict:3 +#: telebot.service_utils.is_pil_image:3 msgid "object to be checked" msgstr "Объект для проверки" -#: of telebot.util.is_bytes:6 +#: of telebot.service_utils.is_bytes:6 msgid "True if the given object is a bytes object." msgstr "True, если полученный объект является bytes." -#: of telebot.util.is_bytes:7 telebot.util.is_command:7 telebot.util.is_dict:7 -#: telebot.util.is_pil_image:7 +#: of telebot.service_utils.is_bytes:7 telebot.service_utils.is_dict:7 +#: telebot.service_utils.is_pil_image:7 telebot.util.is_command:7 msgid ":obj:`bool`" msgstr "" @@ -183,8 +200,8 @@ msgid "" "Checks if `text` is a command. Telegram chat commands start with the '/' " "character." msgstr "" -"Проверяет, является ли `text` командой. Команды в Telegram начинаются " -"с символа '/'." +"Проверяет, является ли `text` командой. Команды в Telegram начинаются с " +"символа '/'." #: of telebot.util.is_command:3 msgid "Text to check." @@ -194,23 +211,23 @@ msgstr "Текст для проверки." msgid "True if `text` is a command, else False." msgstr "True, если `text` является командой, иначе False." -#: of telebot.util.is_dict:1 +#: of telebot.service_utils.is_dict:1 msgid "Returns True if the given object is a dictionary." msgstr "Возвращает True, если полученный объект является словарём (dict)." -#: of telebot.util.is_dict:6 +#: of telebot.service_utils.is_dict:6 msgid "True if the given object is a dictionary." msgstr "True, если полученный объект является словарём (dict)." -#: of telebot.util.is_pil_image:1 +#: of telebot.service_utils.is_pil_image:1 msgid "Returns True if the given object is a PIL.Image.Image object." msgstr "Возвращает True, если полученный объект является PIL.Image.Image." -#: of telebot.util.is_pil_image:6 +#: of telebot.service_utils.is_pil_image:6 msgid "True if the given object is a PIL.Image.Image object." msgstr "True, если полученный объект является PIL.Image.Image." -#: of telebot.util.is_string:1 +#: of telebot.service_utils.is_string:1 msgid "Returns True if the given object is a string." msgstr "Возвращает True, если полученный объект является строкой (str)." @@ -236,9 +253,9 @@ msgid "" "is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2" " = InlineKeyboardButton(...)'" msgstr "" -"Возвращает reply markup из словаря следующего формата: {'text': kwargs}. Удобно " -"использовать вместо постоянного использования 'btn1 = InlineKeyboardButton(...)' 'btn2" -" = InlineKeyboardButton(...)'" +"Возвращает reply markup из словаря следующего формата: {'text': kwargs}. " +"Удобно использовать вместо постоянного использования 'btn1 = " +"InlineKeyboardButton(...)' 'btn2 = InlineKeyboardButton(...)'" #: of telebot.util.quick_markup:4 telebot.util.user_link:5 msgid "Example:" @@ -248,7 +265,7 @@ msgstr "Пример:" msgid "Using quick_markup:" msgstr "Используя quick_markup:" -#: of telebot.util.quick_markup:29 +#: of telebot.util.quick_markup:31 msgid "" "a dict containing all buttons to create in this format: {text: kwargs} " "{str:}" @@ -256,15 +273,15 @@ msgstr "" "Словарь, содержащий все кнопки для создания reply markup в следующем " "формате: {text: kwargs} {str:}" -#: of telebot.util.quick_markup:32 -msgid "int row width" -msgstr "Количество кнопок в одной строке, int" +#: of telebot.util.quick_markup:34 +msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row" +msgstr "" -#: of telebot.util.quick_markup:35 +#: of telebot.util.quick_markup:37 msgid "InlineKeyboardMarkup" msgstr "" -#: of telebot.util.quick_markup:36 +#: of telebot.util.quick_markup:38 msgid ":obj:`types.InlineKeyboardMarkup`" msgstr "" @@ -276,10 +293,11 @@ msgid "" " `chars_per_string` = 4096. Splits by '\\n', '. ' or ' ' in exactly this " "priority." msgstr "" -"Разбивает строку на несколько, каждая из которых будет не длиннее `characters_per_string`. " -"Удобно использовать для разбиения одного гигантского сообщения на несколько. " -"Если `chars_per_string` > 4096: `chars_per_string` = 4096. Разбивает строку по '\\n', '. ' или ' ' " -"именно в таком порядке." +"Разбивает строку на несколько, каждая из которых будет не длиннее " +"`characters_per_string`. Удобно использовать для разбиения одного " +"гигантского сообщения на несколько. Если `chars_per_string` > 4096: " +"`chars_per_string` = 4096. Разбивает строку по '\\n', '. ' или ' ' именно" +" в таком порядке." #: of telebot.util.smart_split:6 telebot.util.split_string:4 msgid "The text to split" @@ -287,7 +305,9 @@ msgstr "Текст для разбиения" #: of telebot.util.smart_split:9 msgid "The number of maximum characters per part the text is split to." -msgstr "Максимальное количество символов в части текста, на которые он будет разбит." +msgstr "" +"Максимальное количество символов в части текста, на которые он будет " +"разбит." #: of telebot.util.smart_split:12 telebot.util.split_string:10 msgid "The splitted text as a list of strings." @@ -303,8 +323,9 @@ msgid "" "`chars_per_string` characters per string. This is very useful for " "splitting one giant message into multiples." msgstr "" -"Разбивает одну строку на несколько, каждая из которых будет не длиннее `characters_per_string`. " -"Удобно использовать для разбиения одного гигантского сообщения на несколько." +"Разбивает одну строку на несколько, каждая из которых будет не длиннее " +"`characters_per_string`. Удобно использовать для разбиения одного " +"гигантского сообщения на несколько." #: of telebot.util.split_string:7 msgid "The number of characters per line the text is split into." @@ -312,15 +333,17 @@ msgstr "Количество символов в одной строке, на #: ../../docstring of telebot.util.update_types:1 msgid "All update types, should be used for allowed_updates parameter in polling." -msgstr "Все виды апдейтов, рекомендуется использовать в качестве параметра allowed_updates функции polling." +msgstr "" +"Все виды апдейтов, рекомендуется использовать в качестве параметра " +"allowed_updates функции polling." #: of telebot.util.user_link:1 msgid "" "Returns an HTML user link. This is useful for reports. Attention: Don't " "forget to set parse_mode to 'HTML'!" msgstr "" -"Возвращает HTML ссылку на пользователя. Удобно использовать для отчетов. Важно: Не " -"забудьте установить значение 'HTML' в parse_mode!" +"Возвращает HTML ссылку на пользователя. Удобно использовать для отчетов. " +"Важно: Не забудьте установить значение 'HTML' в parse_mode!" #: of telebot.util.user_link:11 msgid "" @@ -328,9 +351,10 @@ msgid "" "links, and etc.) This method is kept for backward compatibility, and it " "is recommended to use formatting.* for more options." msgstr "" -"Вы можете использовать formatting.* во всех остальных вариантах форматирования(bold, italic, " -"links, и прочее). Этот метод сохранён для обратной совместимости, рекомендуется " -"использовать formatting.* для большего количества вариантов." +"Вы можете использовать formatting.* во всех остальных вариантах " +"форматирования(bold, italic, links, и прочее). Этот метод сохранён для " +"обратной совместимости, рекомендуется использовать formatting.* для " +"большего количества вариантов." #: of telebot.util.user_link:15 msgid "the user (not the user_id)" @@ -364,3 +388,6 @@ msgstr "HTTP-запрос" msgid "The response object" msgstr "Объект, полученный в качестве ответа" +#~ msgid "int row width" +#~ msgstr "Количество кнопок в одной строке, int" + From 67e3774e8ef59af54b6b71ec69e5cc291bf218bc Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 8 Jul 2023 23:23:23 +0500 Subject: [PATCH 017/480] Fix issue with post_process in async not receiving the error --- telebot/async_telebot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 72e7ad4c0..981ad25e5 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -536,6 +536,7 @@ async def _run_middlewares_and_handlers(self, message, handlers, middlewares, up if not isinstance(result, ContinueHandling): break except Exception as e: + handler_error = e if self.exception_handler: self.exception_handler.handle(e) else: From 916569cdc5c51567ba7fd104f400ee5b8933cc1b Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 8 Jul 2023 23:42:47 +0500 Subject: [PATCH 018/480] Fixes #1944: uploading file from memory --- telebot/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index b793073fd..7f5fc3035 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7250,7 +7250,7 @@ def _resolve_file(self, file): _file = open(file, 'rb') return _file, os.path.basename(_file.name) elif isinstance(file, IOBase): - return file, os.path.basename(file.name) + return file, service_utils.generate_random_token() elif isinstance(file, Path): _file = open(file, 'rb') return _file, os.path.basename(_file.name) @@ -7742,4 +7742,4 @@ def to_dict(self) -> dict: return json_dict def to_json(self) -> str: - return json.dumps(self.to_dict()) \ No newline at end of file + return json.dumps(self.to_dict()) From cb7f6a8c9933a540551868946d936fabf172865c Mon Sep 17 00:00:00 2001 From: Kourva <118578799+Kourva@users.noreply.github.com> Date: Mon, 10 Jul 2023 03:05:34 +0330 Subject: [PATCH 019/480] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index aa8b32ec3..cf6e75fa9 100644 --- a/README.md +++ b/README.md @@ -891,5 +891,6 @@ Here are some examples of template: * [Spot Seek Bot](https://t.me/SpotSeekBot) ([source](https://github.com/arashnm80/spot-seek-bot)) by [Arashnm80](https://github.com/arashnm80). This is a free & open source telegram bot for downloading tracks, albums or playlists from spotify. * [CalendarIT Bot](https://t.me/calendarit_bot) ([source](https://github.com/codebyzen/CalendarIT_Telegram_Bot))by [CodeByZen](https://github.com/codebyzen). A simple, but extensible Python Telegram bot, can post acquainted with what is happening today, tomorrow or what happened 20 years ago to channel. * [DownloadMusicBOT](https://github.com/fcoagz/DownloadMusicBOT) by *Francisco Griman* - It is a simple bot that downloads audio from YouTube videos on Telegram. +* [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles! **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From b18bcd494a6bdcae8ad95379344b3cfb2a36319b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 12 Jul 2023 19:48:22 +0300 Subject: [PATCH 020/480] Fix aioredis version check for regular redis --- telebot/asyncio_storage/redis_storage.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index f9c3aeac3..8d2519b71 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -1,10 +1,11 @@ from telebot.asyncio_storage.base_storage import StateStorageBase, StateContext import json - redis_installed = True +is_actual_aioredis = False try: import aioredis + is_actual_aioredis = True except ImportError: try: from redis import asyncio as aioredis @@ -23,10 +24,10 @@ def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='tel if not redis_installed: raise ImportError('AioRedis is not installed. Install it via "pip install aioredis"') - - aioredis_version = tuple(map(int, aioredis.__version__.split(".")[0])) - if aioredis_version < (2,): - raise ImportError('Invalid aioredis version. Aioredis version should be >= 2.0.0') + if is_actual_aioredis: + aioredis_version = tuple(map(int, aioredis.__version__.split(".")[0])) + if aioredis_version < (2,): + raise ImportError('Invalid aioredis version. Aioredis version should be >= 2.0.0') self.redis = aioredis.Redis(host=host, port=port, db=db, password=password) self.prefix = prefix From 1946393c36d64511f691595e9625718049fafcca Mon Sep 17 00:00:00 2001 From: Artin GH <80193492+Artin-GH@users.noreply.github.com> Date: Fri, 14 Jul 2023 16:39:50 +0330 Subject: [PATCH 021/480] Fix backslash (\) issue in escape_markdown --- telebot/formatting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index ec421c617..32a09fe2d 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -61,8 +61,8 @@ def escape_markdown(content: str) -> str: :rtype: :obj:`str` """ - parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!\{\}])", r"\\\1", content) - reparse = re.sub(r"\\\\([_*\[\]()~`>\#\+\-=|\.!\{\}])", r"\1", parse) + parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!\{\}\\])", r"\\\1", content) + reparse = re.sub(r"\\\\([_*\[\]()~`>\#\+\-=|\.!\{\}\\])", r"\1", parse) return reparse From ebfbfb2dfc416e8c52ceeb03ea0545e3a1f9ea5c Mon Sep 17 00:00:00 2001 From: TheWCKD Date: Mon, 24 Jul 2023 18:38:22 +0300 Subject: [PATCH 022/480] added posibility to handle exception on RequestTimeout --- telebot/async_telebot.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 981ad25e5..b3f189e16 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -415,8 +415,16 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: except asyncio.CancelledError: return except asyncio_helper.RequestTimeout as e: - logger.error(str(e)) - if non_stop: + handled = False + if self.exception_handler: + self.exception_handler.handle(e) + handled = True + + if not handled: + logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) + logger.debug(traceback.format_exc()) + + if non_stop or handled: await asyncio.sleep(2) continue else: From a5cc2f589b49ee14b75a73309bc2f18b783b77ef Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 18 Aug 2023 22:00:14 +0500 Subject: [PATCH 023/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf6e75fa9..c37a19eb4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 6.7! +##

Supported Bot API version: 6.8!

Official documentation

Official ru documentation

From b5112d8330a37af9534c999c842129c65e3972bf Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 18 Aug 2023 22:09:29 +0500 Subject: [PATCH 024/480] Support for stories: is_forwarded_story, story object --- telebot/types.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 7f5fc3035..3d884321e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -821,6 +821,9 @@ class Message(JsonDeserializable): :param sticker: Optional. Message is a sticker, information about the sticker :type sticker: :class:`telebot.types.Sticker` + :param story: Optional. Message is a forwarded story + :type story: :class:`telebot.types.Story` + :param video: Optional. Message is a video, information about the video :type video: :class:`telebot.types.Video` @@ -1177,6 +1180,9 @@ def de_json(cls, json_string): if 'chat_shared' in obj: opts['chat_shared'] = ChatShared.de_json(obj['chat_shared']) content_type = 'chat_shared' + if 'story' in obj: + opts['story'] = Story.de_json(obj['story']) + content_type = 'story' return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod @@ -1274,10 +1280,19 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.write_access_allowed: Optional[WriteAccessAllowed] = None self.user_shared: Optional[UserShared] = None self.chat_shared: Optional[ChatShared] = None + self.story: Optional[Story] = None for key in options: setattr(self, key, options[key]) self.json = json_string + @property + def is_forwarded_story(self): + """ + Returns True if the message is a forwarded story. + """ + # TODO: In future updates this propery might require changes. + return True if self.story is not None else False + def __html_text(self, text, entities): """ Author: @sviat9440 @@ -7743,3 +7758,18 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) + + +class Story(JsonDeserializable): + """ + This object represents a message about a forwarded story in the chat. + Currently holds no information. + """ + + @classmethod + def de_json(cls, json_string): + return cls() + + def __init__(self) -> None: + pass + From 35e765f70b2279bd4bea88e8d050d45719da54da Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 18 Aug 2023 22:14:44 +0500 Subject: [PATCH 025/480] Added the field voter_chat to the class PollAnswer, to contain channel chat voters in Polls. --- telebot/types.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 3d884321e..8fb32fa0b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6695,6 +6695,9 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): :param poll_id: Unique poll identifier :type poll_id: :obj:`str` + :param voter_chat: Optional. The chat that changed the answer to the poll, if the voter is anonymous + :type voter_chat: :class:`telebot.types.Chat` + :param user: The user, who changed the answer to the poll :type user: :class:`telebot.types.User` @@ -6710,12 +6713,16 @@ def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) + if 'voter_chat' in obj: + obj['voter_chat'] = Chat.de_json(obj['voter_chat']) return cls(**obj) - def __init__(self, poll_id, user, option_ids, **kwargs): + def __init__(self, poll_id, user, option_ids, voter_chat=None, **kwargs): self.poll_id: str = poll_id self.user: User = user self.option_ids: List[int] = option_ids + self.voter_chat: Optional[Chat] = voter_chat + def to_json(self): return json.dumps(self.to_dict()) From 1acb15f06f0e869218151c3d04a32274de1fd6cf Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 18 Aug 2023 22:19:14 +0500 Subject: [PATCH 026/480] Added the field emoji_status_expiration_date to the class Chat. --- telebot/types.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 8fb32fa0b..6354c3ebc 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -543,6 +543,10 @@ class Chat(JsonDeserializable): Returned only in getChat. :type emoji_status_custom_emoji_id: :obj:`str` + :param emoji_status_expiration_date: Optional. Expiration date of the emoji status of the other party in a private chat, + if any. Returned only in getChat. + :type emoji_status_expiration_date: :obj:`int` + :param bio: Optional. Bio of the other party in a private chat. Returned only in getChat. :type bio: :obj:`str` @@ -638,7 +642,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, can_set_sticker_set=None, linked_chat_id=None, location=None, join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, - has_hidden_members=None, has_aggressive_anti_spam_enabled=None, **kwargs): + has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -667,6 +671,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.emoji_status_custom_emoji_id: str = emoji_status_custom_emoji_id self.has_hidden_members: bool = has_hidden_members self.has_aggressive_anti_spam_enabled: bool = has_aggressive_anti_spam_enabled + self.emoji_status_expiration_date: int = emoji_status_expiration_date class MessageID(JsonDeserializable): From de568023f6af05e3c511de1f4c7cf4f343d7f152 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 18 Aug 2023 22:23:36 +0500 Subject: [PATCH 027/480] Added the method unpinAllGeneralForumTopicMessages. --- telebot/__init__.py | 18 ++++++++++++++++++ telebot/apihelper.py | 5 +++++ telebot/async_telebot.py | 18 ++++++++++++++++++ telebot/asyncio_helper.py | 5 +++++ 4 files changed, 46 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 77cdd0ded..e4377d2a0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4571,6 +4571,24 @@ def answer_inline_query( return apihelper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, button) + def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bool: + """ + Use this method to clear the list of pinned messages in a General forum topic. + The bot must be an administrator in the chat for this to work and must have the + can_pin_messages administrator right in the supergroup. + Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages + + :param chat_id: Unique identifier for the target chat or username of chat + :type chat_id: :obj:`int` | :obj:`str` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + + return apihelper.unpin_all_general_forum_topic_messages(self.token, chat_id) + def answer_callback_query( self, callback_query_id: int, text: Optional[str]=None, show_alert: Optional[bool]=None, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index a07f1ef91..cf8a03faf 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1585,6 +1585,11 @@ def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_message=No return _make_request(token, method_url, params=payload) +def unpin_all_general_forum_topic_messages(token, chat_id): + method_url = 'unpinAllGeneralForumTopicMessages' + payload = {'chat_id': chat_id} + return _make_request(token, method_url, params=payload, method='post') + # InlineQuery def answer_callback_query(token, callback_query_id, text=None, show_alert=None, url=None, cache_time=None): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 981ad25e5..cde4f0096 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5424,6 +5424,24 @@ async def answer_inline_query( return await asyncio_helper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, button) + async def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bool: + """ + Use this method to clear the list of pinned messages in a General forum topic. + The bot must be an administrator in the chat for this to work and must have the + can_pin_messages administrator right in the supergroup. + Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages + + :param chat_id: Unique identifier for the target chat or username of chat + :type chat_id: :obj:`int` | :obj:`str` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + + return await asyncio_helper.unpin_all_general_forum_topic_messages(self.token, chat_id) + async def answer_callback_query( self, callback_query_id: int, text: Optional[str]=None, show_alert: Optional[bool]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 5a615b397..894b62be5 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1575,6 +1575,11 @@ async def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_mess return await _process_request(token, method_url, params=payload) +async def unpin_all_general_forum_topic_messages(token, chat_id): + method_url = 'unpinAllGeneralForumTopicMessages' + payload = {'chat_id': chat_id} + return await _process_request(token, method_url, params=payload, method='post') + # InlineQuery async def answer_callback_query(token, callback_query_id, text=None, show_alert=None, url=None, cache_time=None): From 9fd6ef3845009eabc0768fb9de44205b5d5ad841 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Sat, 19 Aug 2023 20:58:49 +0500 Subject: [PATCH 028/480] Done with the review --- telebot/types.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 6354c3ebc..a81fad42e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1290,13 +1290,6 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso setattr(self, key, options[key]) self.json = json_string - @property - def is_forwarded_story(self): - """ - Returns True if the message is a forwarded story. - """ - # TODO: In future updates this propery might require changes. - return True if self.story is not None else False def __html_text(self, text, entities): """ @@ -6703,7 +6696,7 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): :param voter_chat: Optional. The chat that changed the answer to the poll, if the voter is anonymous :type voter_chat: :class:`telebot.types.Chat` - :param user: The user, who changed the answer to the poll + :param user: Optional. The user, who changed the answer to the poll :type user: :class:`telebot.types.User` :param option_ids: 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted @@ -6717,14 +6710,15 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): def de_json(cls, json_string): if (json_string is None): return None obj = cls.check_json(json_string) - obj['user'] = User.de_json(obj['user']) + if 'user' in obj: + obj['user'] = User.de_json(obj['user']) if 'voter_chat' in obj: obj['voter_chat'] = Chat.de_json(obj['voter_chat']) return cls(**obj) - def __init__(self, poll_id, user, option_ids, voter_chat=None, **kwargs): + def __init__(self, poll_id, option_ids, user=None, voter_chat=None, **kwargs): self.poll_id: str = poll_id - self.user: User = user + self.user: Optional[User] = user self.option_ids: List[int] = option_ids self.voter_chat: Optional[Chat] = voter_chat @@ -6733,9 +6727,17 @@ def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): - return {'poll_id': self.poll_id, - 'user': self.user.to_dict(), - 'option_ids': self.option_ids} + # Left for backward compatibility, but with no support for voter_chat + json_dict = { + "poll_id": self.poll_id, + "option_ids": self.option_ids + } + if self.user: + json_dict["user"] = self.user.to_dict() + if self.voter_chat: + json_dict["voter_chat"] = self.voter_chat + return json_dict + class ChatLocation(JsonSerializable, JsonDeserializable, Dictionaryable): @@ -7780,7 +7782,10 @@ class Story(JsonDeserializable): @classmethod def de_json(cls, json_string): - return cls() + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) def __init__(self) -> None: pass From ca41526bcb4e8c810b5f3d486da5d24d9a596904 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 20 Aug 2023 09:06:56 +0300 Subject: [PATCH 029/480] Bump version to 4.13.0 --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f698fc698..ed241d5ee 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.12.0' +release = '4.13.0' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index b42b55928..68dfd5046 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.12.0' +__version__ = '4.13.0' From 09f9fb49e536bea85248d94d3c14dcad361740f9 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 20 Aug 2023 09:13:31 +0300 Subject: [PATCH 030/480] Removed python 3.7, added pypy 3.10 --- .github/workflows/setup_python.yml | 2 +- .readthedocs.yml | 4 ++-- .travis.yml | 1 - README.md | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index ac436e848..2a9787e25 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9'] + python-version: [ '3.8', '3.9', '3.10', '3.11', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] name: ${{ matrix.python-version }} and tests steps: - uses: actions/checkout@v2 diff --git a/.readthedocs.yml b/.readthedocs.yml index 859c13484..0a15ad409 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -14,6 +14,6 @@ formats: all # Optionally set the version of Python and requirements required to build your docs python: - version: 3.7 + version: 3.11 install: - - requirements: doc_req.txt \ No newline at end of file + - requirements: doc_req.txt diff --git a/.travis.yml b/.travis.yml index d316070b1..8e6b02e5c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - "3.7" - "3.8" - "3.9" - "3.10" diff --git a/README.md b/README.md index c37a19eb4..477954916 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ## Getting started -This API is tested with Python 3.7-3.11 and Pypy 3. +This API is tested with Python 3.8-3.11 and Pypy 3. There are two ways to install the library: * Installation using pip (a Python package manager): From 24ec1254a38ee523148f58c053487c210b14346e Mon Sep 17 00:00:00 2001 From: Cub11k Date: Fri, 8 Sep 2023 20:13:34 +0300 Subject: [PATCH 031/480] Add redis_url to StateRedisStorage to allow initialization by URL Useful for rediss:// and unix:// schemes --- telebot/asyncio_storage/redis_storage.py | 7 +++++-- telebot/storage/redis_storage.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index 8d2519b71..84db253e5 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -20,7 +20,7 @@ class StateRedisStorage(StateStorageBase): To use it, just pass this class to: TeleBot(storage=StateRedisStorage()) """ - def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_'): + def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_', redis_url=None): if not redis_installed: raise ImportError('AioRedis is not installed. Install it via "pip install aioredis"') @@ -28,7 +28,10 @@ def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='tel aioredis_version = tuple(map(int, aioredis.__version__.split(".")[0])) if aioredis_version < (2,): raise ImportError('Invalid aioredis version. Aioredis version should be >= 2.0.0') - self.redis = aioredis.Redis(host=host, port=port, db=db, password=password) + if redis_url: + self.redis = aioredis.Redis.from_url(redis_url) + else: + self.redis = aioredis.Redis(host=host, port=port, db=db, password=password) self.prefix = prefix #self.con = Redis(connection_pool=self.redis) -> use this when necessary diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 453d6ae33..3fac57c46 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -15,9 +15,12 @@ class StateRedisStorage(StateStorageBase): To use it, just pass this class to: TeleBot(storage=StateRedisStorage()) """ - def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_'): + def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_', redis_url=None): super().__init__() - self.redis = ConnectionPool(host=host, port=port, db=db, password=password) + if redis_url: + self.redis = ConnectionPool.from_url(redis_url) + else: + self.redis = ConnectionPool(host=host, port=port, db=db, password=password) #self.con = Redis(connection_pool=self.redis) -> use this when necessary # # {chat_id: {user_id: {'state': None, 'data': {}}, ...}, ...} From b2d5bec9c0024d4fb5ff88c7a8630ffd73619402 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 22 Sep 2023 23:29:33 +0400 Subject: [PATCH 032/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 477954916..4dc98ea5b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 6.8! +##

Supported Bot API version: 6.9!

Official documentation

Official ru documentation

From e904b9112be245d979a8117c122cf7cc075955c8 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 22 Sep 2023 23:36:52 +0400 Subject: [PATCH 033/480] Added the new administrator privileges can_post_stories, can_edit_stories and can_delete_stories to the classes ChatMemberAdministrator and ChatAdministratorRights. --- telebot/types.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index a81fad42e..6e49a0cb0 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2888,6 +2888,7 @@ def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_ed can_send_other_messages=None, can_add_web_page_previews=None, can_manage_chat=None, can_manage_video_chats=None, until_date=None, can_manage_topics=None, + can_post_stories=None, can_edit_stories=None, can_delete_stories=None, **kwargs): self.user: User = user self.status: str = status @@ -2919,6 +2920,9 @@ def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_ed self.can_send_videos: bool = can_send_videos self.can_send_video_notes: bool = can_send_video_notes self.can_send_voice_notes: bool = can_send_voice_notes + self.can_post_stories: bool = can_post_stories + self.can_edit_stories: bool = can_edit_stories + self.can_delete_stories: bool = can_delete_stories @@ -3006,6 +3010,15 @@ class ChatMemberAdministrator(ChatMember): :param custom_title: Optional. Custom title for this user :type custom_title: :obj:`str` + :param can_post_stories: Optional. True, if the administrator can post channel stories + :type can_post_stories: :obj:`bool` + + :param can_edit_stories: Optional. True, if the administrator can edit stories + :type can_edit_stories: :obj:`bool` + + :param can_delete_stories: Optional. True, if the administrator can delete stories of other users + :type can_delete_stories: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberAdministrator` """ @@ -7179,6 +7192,15 @@ class ChatAdministratorRights(JsonDeserializable, JsonSerializable, Dictionaryab :param can_manage_topics: Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only :type can_manage_topics: :obj:`bool` + :param can_post_stories: Optional. True, if the administrator can post channel stories + :type can_post_stories: :obj:`bool` + + :param can_edit_stories: Optional. True, if the administrator can edit stories + :type can_edit_stories: :obj:`bool` + + :param can_delete_stories: Optional. True, if the administrator can delete stories of other users + :type can_delete_stories: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.ChatAdministratorRights` """ @@ -7193,7 +7215,10 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_delete_messages: bool, can_manage_video_chats: bool, can_restrict_members: bool, can_promote_members: bool, can_change_info: bool, can_invite_users: bool, can_post_messages: bool=None, can_edit_messages: bool=None, - can_pin_messages: bool=None, can_manage_topics: bool=None) -> None: + can_pin_messages: bool=None, can_manage_topics: bool=None, + can_post_stories: bool=None, can_edit_stories: bool=None, + can_delete_stories: bool=None + ) -> None: self.is_anonymous: bool = is_anonymous self.can_manage_chat: bool = can_manage_chat @@ -7207,6 +7232,9 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, self.can_edit_messages: bool = can_edit_messages self.can_pin_messages: bool = can_pin_messages self.can_manage_topics: bool = can_manage_topics + self.can_post_stories: bool = can_post_stories + self.can_edit_stories: bool = can_edit_stories + self.can_delete_stories: bool = can_delete_stories def to_dict(self): json_dict = { @@ -7227,6 +7255,13 @@ def to_dict(self): json_dict['can_pin_messages'] = self.can_pin_messages if self.can_manage_topics is not None: json_dict['can_manage_topics'] = self.can_manage_topics + if self.can_post_stories is not None: + json_dict['can_post_stories'] = self.can_post_stories + if self.can_edit_stories is not None: + json_dict['can_edit_stories'] = self.can_edit_stories + if self.can_delete_stories is not None: + json_dict['can_delete_stories'] = self.can_delete_stories + return json_dict def to_json(self): From d787862f77de959e4c9b4b3058d7a63431a8be34 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 22 Sep 2023 23:42:12 +0400 Subject: [PATCH 034/480] Added the parameters can_post_stories, can_edit_stories and can_delete_stories to the method promoteChatMember. Currently, bots have no use for these privileges besides assigning them to other administrators. --- telebot/__init__.py | 17 +++++++++++++++-- telebot/apihelper.py | 9 ++++++++- telebot/async_telebot.py | 17 +++++++++++++++-- telebot/asyncio_helper.py | 9 ++++++++- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index e4377d2a0..3e0258a4c 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3058,7 +3058,10 @@ def promote_chat_member( can_manage_chat: Optional[bool]=None, can_manage_video_chats: Optional[bool]=None, can_manage_voice_chats: Optional[bool]=None, - can_manage_topics: Optional[bool]=None) -> bool: + can_manage_topics: Optional[bool]=None, + can_post_stories: Optional[bool]=None, + can_edit_stories: Optional[bool]=None, + can_delete_stories: Optional[bool]=None) -> bool: """ Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -3119,6 +3122,15 @@ def promote_chat_member( and reopen forum topics, supergroups only :type can_manage_topics: :obj:`bool` + :param can_post_stories: Pass True if the administrator can create the channel's stories + :type can_post_stories: :obj:`bool` + + :param can_edit_stories: Pass True if the administrator can edit the channel's stories + :type can_edit_stories: :obj:`bool` + + :param can_delete_stories: Pass True if the administrator can delete the channel's stories + :type can_delete_stories: :obj:`bool` + :return: True on success. :rtype: :obj:`bool` """ @@ -3131,7 +3143,8 @@ def promote_chat_member( self.token, chat_id, user_id, can_change_info, can_post_messages, can_edit_messages, can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, - is_anonymous, can_manage_chat, can_manage_video_chats, can_manage_topics) + is_anonymous, can_manage_chat, can_manage_video_chats, can_manage_topics, + can_post_stories, can_edit_stories, can_delete_stories) def set_chat_administrator_custom_title( self, chat_id: Union[int, str], user_id: int, custom_title: str) -> bool: diff --git a/telebot/apihelper.py b/telebot/apihelper.py index cf8a03faf..902d6e5ca 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -991,7 +991,8 @@ def promote_chat_member( can_edit_messages=None, can_delete_messages=None, can_invite_users=None, can_restrict_members=None, can_pin_messages=None, can_promote_members=None, is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None, - can_manage_topics=None): + can_manage_topics=None, can_post_stories=None, can_edit_stories=None, + can_delete_stories=None): method_url = 'promoteChatMember' payload = {'chat_id': chat_id, 'user_id': user_id} if can_change_info is not None: @@ -1018,6 +1019,12 @@ def promote_chat_member( payload['can_manage_video_chats'] = can_manage_video_chats if can_manage_topics is not None: payload['can_manage_topics'] = can_manage_topics + if can_post_stories is not None: + payload['can_post_stories'] = can_post_stories + if can_edit_stories is not None: + payload['can_edit_stories'] = can_edit_stories + if can_delete_stories is not None: + payload['can_delete_stories'] = can_delete_stories return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 91d0709c6..8d833923f 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3921,7 +3921,10 @@ async def promote_chat_member( can_manage_chat: Optional[bool]=None, can_manage_video_chats: Optional[bool]=None, can_manage_voice_chats: Optional[bool]=None, - can_manage_topics: Optional[bool]=None) -> bool: + can_manage_topics: Optional[bool]=None, + can_post_stories: Optional[bool]=None, + can_edit_stories: Optional[bool]=None, + can_delete_stories: Optional[bool]=None) -> bool: """ Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -3982,6 +3985,15 @@ async def promote_chat_member( and reopen forum topics, supergroups only :type can_manage_topics: :obj:`bool` + :param can_post_stories: Pass True if the administrator can create the channel's stories + :type can_post_stories: :obj:`bool` + + :param can_edit_stories: Pass True if the administrator can edit the channel's stories + :type can_edit_stories: :obj:`bool` + + :param can_delete_stories: Pass True if the administrator can delete the channel's stories + :type can_delete_stories: :obj:`bool` + :return: True on success. :rtype: :obj:`bool` """ @@ -3995,7 +4007,8 @@ async def promote_chat_member( self.token, chat_id, user_id, can_change_info, can_post_messages, can_edit_messages, can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, - is_anonymous, can_manage_chat, can_manage_video_chats, can_manage_topics) + is_anonymous, can_manage_chat, can_manage_video_chats, can_manage_topics, + can_post_stories, can_edit_stories, can_delete_stories) async def set_chat_administrator_custom_title( self, chat_id: Union[int, str], user_id: int, custom_title: str) -> bool: diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 894b62be5..526166eec 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -983,7 +983,8 @@ async def promote_chat_member( token, chat_id, user_id, can_change_info=None, can_post_messages=None, can_edit_messages=None, can_delete_messages=None, can_invite_users=None, can_restrict_members=None, can_pin_messages=None, can_promote_members=None, - is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None, can_manage_topics=None): + is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None, can_manage_topics=None, + can_post_stories=None, can_edit_stories=None, can_delete_stories=None): method_url = 'promoteChatMember' payload = {'chat_id': chat_id, 'user_id': user_id} if can_change_info is not None: @@ -1010,6 +1011,12 @@ async def promote_chat_member( payload['can_manage_video_chats'] = can_manage_video_chats if can_manage_topics is not None: payload['can_manage_topics'] = can_manage_topics + if can_post_stories is not None: + payload['can_post_stories'] = can_post_stories + if can_edit_stories is not None: + payload['can_edit_stories'] = can_edit_stories + if can_delete_stories is not None: + payload['can_delete_stories'] = can_delete_stories return await _process_request(token, method_url, params=payload, method='post') From 1565bc05f733cb68287b39f5591d55bd042fae6d Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 22 Sep 2023 23:45:46 +0400 Subject: [PATCH 035/480] Added the fields from_request and from_attachment_menu to the class WriteAccessAllowed. --- telebot/types.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 6e49a0cb0..73efd5592 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7261,7 +7261,7 @@ def to_dict(self): json_dict['can_edit_stories'] = self.can_edit_stories if self.can_delete_stories is not None: json_dict['can_delete_stories'] = self.can_delete_stories - + return json_dict def to_json(self): @@ -7482,13 +7482,21 @@ def __init__(self, message_thread_id: int, name: str, icon_color: int, icon_cust class WriteAccessAllowed(JsonDeserializable): """ - This object represents a service message about a user allowed to post messages in the chat. - Currently holds no information. + This object represents a service message about a user allowing a bot to write + messages after adding it to the attachment menu, launching a Web App from a link, + or accepting an explicit request from a Web App sent by the method requestWriteAccess. Telegram documentation: https://core.telegram.org/bots/api#writeaccessallowed + :param from_request: Optional. True, if the access was granted after the user accepted an + explicit request from a Web App sent by the method requestWriteAccess + :type from_request: :obj:`bool` + :param web_app_name: Optional. Name of the Web App which was launched from a link :type web_app_name: :obj:`str` + + :param from_attachment_menu: Optional. True, if the access was granted when the bot was added to the attachment or side menu + :type from_attachment_menu: :obj:`bool` """ @classmethod def de_json(cls, json_string): @@ -7497,8 +7505,10 @@ def de_json(cls, json_string): return cls(**obj) - def __init__(self, web_app_name: str) -> None: + def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str]=None, from_attachment_menu: Optional[bool]=None) -> None: self.web_app_name: str = web_app_name + self.from_request: bool = from_request + self.from_attachment_menu: bool = from_attachment_menu From 9d36e4c49f399e234236e3253a67dc4204fc17ae Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 24 Sep 2023 11:23:59 +0300 Subject: [PATCH 036/480] Bump version to 4.14.0 --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index ed241d5ee..499e7d3b5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.13.0' +release = '4.14.0' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index 68dfd5046..99a734c84 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.13.0' +__version__ = '4.14.0' From 94913a076a058821b2ba326739c1f0ba98e22a13 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Tue, 3 Oct 2023 12:20:54 +0300 Subject: [PATCH 037/480] Fix protect_content hint --- telebot/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 3e0258a4c..cb145c664 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1517,7 +1517,7 @@ def send_message( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param protect_content: If True, the message content will be hidden for all users except for the target user + :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` :param reply_to_message_id: If the message is a reply, ID of the original message @@ -1733,7 +1733,7 @@ def send_dice( :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding + :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` :param message_thread_id: Identifier of a message thread, in which the message will be sent @@ -3942,7 +3942,7 @@ def send_game( :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified replied-to messages is not found. :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Pass True, if content of the message needs to be protected from being viewed by the bot. + :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` :param message_thread_id: The identifier of a message thread, in which the game message will be sent. From c2869fcf5a2b1b4abad10f2168a4fdcf8f7ec476 Mon Sep 17 00:00:00 2001 From: alexsuhor <76397241+alexsuhor@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:38:26 +0500 Subject: [PATCH 038/480] Update README.md should have to functions -> should have two functions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4dc98ea5b..f545ccb50 100644 --- a/README.md +++ b/README.md @@ -374,7 +374,7 @@ class Middleware(BaseMiddleware): if exception: # check for exception print(exception) ``` -Class-based middleware should have to functions: post and pre process. +Class-based middleware should have two functions: post and pre process. So, as you can see, class-based middlewares work before and after handler execution. For more, check out in [examples](https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/middleware/class_based) From aacaf5b311024efcbf944dfe860baf12770dfbaf Mon Sep 17 00:00:00 2001 From: Arash Nemat Zadeh Date: Sat, 28 Oct 2023 21:12:04 +0330 Subject: [PATCH 039/480] adding QR-Code Generator bot to the list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f545ccb50..1f447e7e8 100644 --- a/README.md +++ b/README.md @@ -892,5 +892,6 @@ Here are some examples of template: * [CalendarIT Bot](https://t.me/calendarit_bot) ([source](https://github.com/codebyzen/CalendarIT_Telegram_Bot))by [CodeByZen](https://github.com/codebyzen). A simple, but extensible Python Telegram bot, can post acquainted with what is happening today, tomorrow or what happened 20 years ago to channel. * [DownloadMusicBOT](https://github.com/fcoagz/DownloadMusicBOT) by *Francisco Griman* - It is a simple bot that downloads audio from YouTube videos on Telegram. * [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles! +* [QR-Code For You Bot](https://t.me/qrcode_for_you_bot) ([source](https://github.com/arashnm80/qrcode-for-you-bot)) by [Arashnm80](https://github.com/arashnm80). Telegram qrcode generator bot created with pyhton and telebot. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From ce48dd9c16c5c3eb3b8d5458f3657ca36c97dd05 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 29 Oct 2023 17:45:11 +0300 Subject: [PATCH 040/480] Sending InputFile fix send_document with InputFile and visible_file_name fails to be sent. --- telebot/apihelper.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 902d6e5ca..bfee49967 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -94,7 +94,9 @@ def _make_request(token, method_name, method='get', params=None, files=None): for key, value in files_copy.items(): if isinstance(value, types.InputFile): files[key] = value.file - + elif isinstance(value, tuple) and (len(value) == 2) and isinstance(value[1], types.InputFile): + files[key] = (value[0], value[1].file) + if files and format_header_param: fields.format_header_param = _no_encode(format_header_param) From 9c569e1d29121bfaeb500a04c08c5bfd2fe49d75 Mon Sep 17 00:00:00 2001 From: Arash Nemat Zadeh Date: Thu, 9 Nov 2023 00:27:04 +0330 Subject: [PATCH 041/480] add instagram downloader to bots list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1f447e7e8..0262e781d 100644 --- a/README.md +++ b/README.md @@ -893,5 +893,6 @@ Here are some examples of template: * [DownloadMusicBOT](https://github.com/fcoagz/DownloadMusicBOT) by *Francisco Griman* - It is a simple bot that downloads audio from YouTube videos on Telegram. * [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles! * [QR-Code For You Bot](https://t.me/qrcode_for_you_bot) ([source](https://github.com/arashnm80/qrcode-for-you-bot)) by [Arashnm80](https://github.com/arashnm80). Telegram qrcode generator bot created with pyhton and telebot. +* [Best Instagram Downloader Bot](https://t.me/Best_Instagram_Downloader_Bot) ([source](https://github.com/arashnm80/best-instagram-downloader)) by [Arashnm80](https://github.com/arashnm80). Free and open source telegram bot to download posts and reels from Instagram. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From a1bb69540cf8abc47e1f98d973ec3e65f0ea6bcd Mon Sep 17 00:00:00 2001 From: Alexander Osipov Date: Wed, 8 Nov 2023 16:40:14 +0300 Subject: [PATCH 042/480] Fix ExceptionHandler handle() method as async for async telebot issue https://github.com/eternnoir/pyTelegramBotAPI/issues/2070 --- .../asynchronous_telebot/exception_handler.py | 19 ++++------ telebot/__init__.py | 37 +++++++------------ telebot/async_telebot.py | 35 ++++++++---------- 3 files changed, 37 insertions(+), 54 deletions(-) diff --git a/examples/asynchronous_telebot/exception_handler.py b/examples/asynchronous_telebot/exception_handler.py index b37f94508..cbf1540a9 100644 --- a/examples/asynchronous_telebot/exception_handler.py +++ b/examples/asynchronous_telebot/exception_handler.py @@ -1,28 +1,25 @@ +import logging import telebot -from telebot.async_telebot import AsyncTeleBot - - -import logging +from telebot.async_telebot import AsyncTeleBot, ExceptionHandler logger = telebot.logger -telebot.logger.setLevel(logging.DEBUG) # Outputs debug messages to console. +telebot.logger.setLevel(logging.DEBUG) # Outputs debug messages to console. -class ExceptionHandler(telebot.ExceptionHandler): - def handle(self, exception): - logger.error(exception) -bot = AsyncTeleBot('TOKEN',exception_handler=ExceptionHandler()) +class MyExceptionHandler(ExceptionHandler): + async def handle(self, exception): + logger.error(exception) +bot = AsyncTeleBot('TOKEN', exception_handler=MyExceptionHandler()) @bot.message_handler(commands=['photo']) async def photo_send(message: telebot.types.Message): await bot.send_message(message.chat.id, 'Hi, this is an example of exception handlers.') - raise Exception('test') # Exception goes to ExceptionHandler if it is set + raise Exception('test') # Exception goes to ExceptionHandler if it is set - import asyncio asyncio.run(bot.polling()) diff --git a/telebot/__init__.py b/telebot/__init__.py index cb145c664..7d06cf90d 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1046,6 +1046,12 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F self.__non_threaded_polling(non_stop=non_stop, interval=interval, timeout=timeout, long_polling_timeout=long_polling_timeout, logger_level=logger_level, allowed_updates=allowed_updates) + def _handle_exception(self, exception: Exception) -> bool: + if self.exception_handler is None: + return False + + handled = self.exception_handler.handle(exception) + return handled def __threaded_polling(self, non_stop = False, interval = 0, timeout = None, long_polling_timeout = None, logger_level=logging.ERROR, allowed_updates=None): @@ -1074,10 +1080,7 @@ def __threaded_polling(self, non_stop = False, interval = 0, timeout = None, lon self.worker_pool.raise_exceptions() error_interval = 0.25 except apihelper.ApiException as e: - if self.exception_handler is not None: - handled = self.exception_handler.handle(e) - else: - handled = False + handled = self._handle_exception(e) if not handled: if logger_level and logger_level >= logging.ERROR: logger.error("Threaded polling exception: %s", str(e)) @@ -1107,10 +1110,7 @@ def __threaded_polling(self, non_stop = False, interval = 0, timeout = None, lon self.__stop_polling.set() break except Exception as e: - if self.exception_handler is not None: - handled = self.exception_handler.handle(e) - else: - handled = False + handled = self._handle_exception(e) if not handled: polling_thread.stop() polling_thread.clear_exceptions() #* @@ -1144,11 +1144,7 @@ def __non_threaded_polling(self, non_stop=False, interval=0, timeout=None, long_ self.__retrieve_updates(timeout, long_polling_timeout, allowed_updates=allowed_updates) error_interval = 0.25 except apihelper.ApiException as e: - if self.exception_handler is not None: - handled = self.exception_handler.handle(e) - else: - handled = False - + handled = self._handle_exception(e) if not handled: if logger_level and logger_level >= logging.ERROR: logger.error("Polling exception: %s", str(e)) @@ -1171,10 +1167,7 @@ def __non_threaded_polling(self, non_stop=False, interval=0, timeout=None, long_ self.__stop_polling.set() break except Exception as e: - if self.exception_handler is not None: - handled = self.exception_handler.handle(e) - else: - handled = False + handled = self._handle_exception(e) if not handled: raise e else: @@ -1190,10 +1183,7 @@ def _exec_task(self, task, *args, **kwargs): try: task(*args, **kwargs) except Exception as e: - if self.exception_handler is not None: - handled = self.exception_handler.handle(e) - else: - handled = False + handled = self._handle_exception(e) if not handled: raise e @@ -6858,9 +6848,8 @@ def _run_middlewares_and_handler(self, message, handlers, middlewares, update_ty break except Exception as e: handler_error = e - if self.exception_handler: - self.exception_handler.handle(e) - else: + handled = self._handle_exception(e) + if not handled: logger.error(str(e)) logger.debug("Exception traceback:\n%s", traceback.format_exc()) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8d833923f..cd71abeac 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -58,7 +58,7 @@ class ExceptionHandler: """ # noinspection PyMethodMayBeStatic,PyUnusedLocal - def handle(self, exception): + async def handle(self, exception): return False @@ -368,6 +368,16 @@ async def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Option if logger_level and logger_level >= logging.INFO: logger.error("Break infinity polling") + async def _handle_exception(self, exception: Exception) -> bool: + if self.exception_handler is None: + return False + + if iscoroutinefunction(self.exception_handler.handle): + handled = await self.exception_handler.handle(exception) + else: + handled = self.exception_handler.handle(exception) # noqa + return handled + async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: int=20, request_timeout: int=None, allowed_updates: Optional[List[str]]=None): """ @@ -415,11 +425,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: except asyncio.CancelledError: return except asyncio_helper.RequestTimeout as e: - handled = False - if self.exception_handler: - self.exception_handler.handle(e) - handled = True - + handled = await self._handle_exception(e) if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) logger.debug(traceback.format_exc()) @@ -430,11 +436,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: else: return except asyncio_helper.ApiException as e: - handled = False - if self.exception_handler: - self.exception_handler.handle(e) - handled = True - + handled = await self._handle_exception(e) if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) logger.debug(traceback.format_exc()) @@ -444,11 +446,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: else: break except Exception as e: - handled = False - if self.exception_handler: - self.exception_handler.handle(e) - handled = True - + handled = await self._handle_exception(e) if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) logger.debug(traceback.format_exc()) @@ -545,9 +543,8 @@ async def _run_middlewares_and_handlers(self, message, handlers, middlewares, up break except Exception as e: handler_error = e - if self.exception_handler: - self.exception_handler.handle(e) - else: + handled = await self._handle_exception(e) + if not handled: logger.error(str(e)) logger.debug("Exception traceback:\n%s", traceback.format_exc()) From 62e195aae46c0df9f45ba4439323e5cfa0fea619 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 19 Nov 2023 11:23:12 +0300 Subject: [PATCH 043/480] Some code clearing --- telebot/__init__.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 7d06cf90d..ac92a38c4 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -175,14 +175,16 @@ def __init__( self.token = token self.skip_pending = skip_pending # backward compatibility self.last_update_id = last_update_id - - # propertys + + # properties self.suppress_middleware_excepions = suppress_middleware_excepions self.parse_mode = parse_mode self.disable_web_page_preview = disable_web_page_preview self.disable_notification = disable_notification self.protect_content = protect_content self.allow_sending_without_reply = allow_sending_without_reply + self.webhook_listener = None + self._user = None # logs-related if colorful_logs: @@ -269,7 +271,7 @@ def user(self) -> types.User: :return: Bot's info. :rtype: :class:`telebot.types.User` """ - if not hasattr(self, "_user"): + if not self._user: self._user = self.get_me() return self._user @@ -1055,7 +1057,7 @@ def _handle_exception(self, exception: Exception) -> bool: def __threaded_polling(self, non_stop = False, interval = 0, timeout = None, long_polling_timeout = None, logger_level=logging.ERROR, allowed_updates=None): - if not(logger_level) or (logger_level < logging.INFO): + if (not logger_level) or (logger_level < logging.INFO): warning = "\n Warning: this message appearance will be changed. Set logger_level=logging.INFO to continue seeing it." else: warning = "" @@ -1130,7 +1132,7 @@ def __threaded_polling(self, non_stop = False, interval = 0, timeout = None, lon def __non_threaded_polling(self, non_stop=False, interval=0, timeout=None, long_polling_timeout=None, logger_level=logging.ERROR, allowed_updates=None): - if not(logger_level) or (logger_level < logging.INFO): + if (not logger_level) or (logger_level < logging.INFO): warning = "\n Warning: this message appearance will be changed. Set logger_level=logging.INFO to continue seeing it." else: warning = "" @@ -2076,7 +2078,7 @@ def send_document( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if data and not(document): + if data and (not document): # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "document" instead.') document = data @@ -2157,7 +2159,7 @@ def send_sticker( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if data and not(sticker): + if data and (not sticker): # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data @@ -2265,7 +2267,7 @@ def send_video( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if data and not(video): + if data and (not video): # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "video" instead.') video = data @@ -6872,7 +6874,7 @@ def _notify_command_handlers(self, handlers, new_messages, update_type): :param update_type: handler/update type (Update fields) :return: """ - if not(handlers) and not(self.use_class_middlewares): + if (not handlers) and (not self.use_class_middlewares): return if self.use_class_middlewares: From 5fd60380db0de83049d35c66ce1794b988ed6471 Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Mon, 20 Nov 2023 21:44:50 +0400 Subject: [PATCH 044/480] Fix telebot.types.Message.html_text may contain unescaped HTML characters. --- telebot/types.py | 4 ++-- tests/test_types.py | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 73efd5592..221ba2fab 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1294,7 +1294,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso def __html_text(self, text, entities): """ Author: @sviat9440 - Updaters: @badiboy + Updaters: @badiboy, @EgorKhabarov Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" .. code-block:: python3 @@ -1314,7 +1314,7 @@ def __html_text(self, text, entities): """ if not entities: - return text + return text.replace("&", "&").replace("<", "<").replace(">", ">") _subs = { "bold": "{text}", diff --git a/tests/test_types.py b/tests/test_types.py index 138c36b8c..06bcae1ee 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -295,7 +295,15 @@ def test_message_entity(): message_4 = types.Update.de_json(sample_string_4).message assert message_4.html_text == 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa😋😋' - + + sample_string_5 = r'{"update_id":934522166,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"text":"b b i","entities":[{"offset":0,"length":1,"type":"bold"}]}}' + message_5 = types.Update.de_json(sample_string_5).message + assert message_5.html_text == "b <b>b</b> <i>i</i>" + + + sample_string_6 = r'{"update_id":934522166,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"text":"b i"}}' + message_6 = types.Update.de_json(sample_string_6).message + assert message_6.html_text == "<b>b</b> <i>i</i>" From 3f3d41159276ba08ff00b4d8e0d212525f15177b Mon Sep 17 00:00:00 2001 From: Ali Toosi Date: Mon, 4 Dec 2023 15:37:57 +1100 Subject: [PATCH 045/480] Add new content_types in docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0262e781d..639bfe00b 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ To start the bot, simply open up a terminal and enter `python echo_bot.py` to ru All types are defined in types.py. They are all completely in line with the [Telegram API's definition of the types](https://core.telegram.org/bots/api#available-types), except for the Message's `from` field, which is renamed to `from_user` (because `from` is a Python reserved token). Thus, attributes such as `message_id` can be accessed directly with `message.message_id`. Note that `message.chat` can be either an instance of `User` or `GroupChat` (see [How can I distinguish a User and a GroupChat in message.chat?](#how-can-i-distinguish-a-user-and-a-groupchat-in-messagechat)). The Message object also has a `content_type`attribute, which defines the type of the Message. `content_type` can be one of the following strings: -`text`, `audio`, `document`, `photo`, `sticker`, `video`, `video_note`, `voice`, `location`, `contact`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`, `web_app_data`. +`text`, `audio`, `document`, `animation`, `game`, `photo`, `sticker`, `video`, `video_note`, `voice`, `location`, `contact`, `venue`, `dice`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`, `invoice`, `successful_payment`, `connected_website`, `poll`, `passport_data`, `proximity_alert_triggered`, `video_chat_scheduled`, `video_chat_started`, `video_chat_ended`, `video_chat_participants_invited`, `web_app_data`, `message_auto_delete_timer_changed`, `forum_topic_created`, `forum_topic_closed`, `forum_topic_reopened`, `forum_topic_edited`, `general_forum_topic_hidden`, `general_forum_topic_unhidden`, `write_access_allowed`, `user_shared`, `chat_shared`, `story`. You can use some types in one function. Example: From 0ecfb19721de4e5810a329bc13c6f63d13996d13 Mon Sep 17 00:00:00 2001 From: Matvey Aslandukov Date: Sat, 9 Dec 2023 12:49:26 +0200 Subject: [PATCH 046/480] Specified correct return type --- telebot/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index ac92a38c4..4a4324507 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1645,8 +1645,8 @@ def copy_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` - :return: On success, the sent Message is returned. - :rtype: :class:`telebot.types.Message` + :return: On success, the MessageId of the sent message is returned. + :rtype: :class:`telebot.types.MessageID` """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification parse_mode = self.parse_mode if (parse_mode is None) else parse_mode From 7a8559c314bbb2a5aa877a6796345bdfbcd9e386 Mon Sep 17 00:00:00 2001 From: Matvey Aslandukov Date: Sat, 9 Dec 2023 12:57:41 +0200 Subject: [PATCH 047/480] Specified correct return type in the async_telebot --- telebot/async_telebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index cd71abeac..92748a9fc 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2521,8 +2521,8 @@ async def copy_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` - :return: On success, the sent Message is returned. - :rtype: :class:`telebot.types.Message` + :return: On success, the MessageId of the sent message is returned. + :rtype: :class:`telebot.types.MessageID` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification From 3d4a5d5d3b7e5b5b5dd632f2bd4113aba5c9cc8b Mon Sep 17 00:00:00 2001 From: Simatwa Date: Mon, 18 Dec 2023 17:35:03 +0300 Subject: [PATCH 048/480] Add telegram-chatbots --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 639bfe00b..9d49ff2e7 100644 --- a/README.md +++ b/README.md @@ -894,5 +894,6 @@ Here are some examples of template: * [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles! * [QR-Code For You Bot](https://t.me/qrcode_for_you_bot) ([source](https://github.com/arashnm80/qrcode-for-you-bot)) by [Arashnm80](https://github.com/arashnm80). Telegram qrcode generator bot created with pyhton and telebot. * [Best Instagram Downloader Bot](https://t.me/Best_Instagram_Downloader_Bot) ([source](https://github.com/arashnm80/best-instagram-downloader)) by [Arashnm80](https://github.com/arashnm80). Free and open source telegram bot to download posts and reels from Instagram. +* [Personal bot for ChatGPT & Bard](https://github.com/Simatwa/pyTelegramBotAPI.git) by [Simatwa](https://github.com/Simatwa/telegram-chatbots). Chat with ChatGPT & Bard on the go. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From 4f8866818e2cf967d22e24ae2297c062e4780dff Mon Sep 17 00:00:00 2001 From: anonymousdouble <112695649+anonymousdouble@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:15:22 +1100 Subject: [PATCH 049/480] Update test_telebot.py refactor with With statement to open file to make code more Pythonic --- tests/test_telebot.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 0caff9e86..280a19f7c 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -175,10 +175,10 @@ def test_send_video(self): assert ret_msg.message_id def test_send_video_dis_noti(self): - file_data = open('./test_data/test_video.mp4', 'rb') - tb = telebot.TeleBot(TOKEN) - ret_msg = tb.send_video(CHAT_ID, file_data, disable_notification=True) - assert ret_msg.message_id + with open('./test_data/test_video.mp4', 'rb') as file_data: + tb = telebot.TeleBot(TOKEN) + ret_msg = tb.send_video(CHAT_ID, file_data, disable_notification=True) + assert ret_msg.message_id def test_send_video_more_params(self): file_data = open('./test_data/test_video.mp4', 'rb') From 3145269043955c5ed30193d29d513b1096ba0d00 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 20 Dec 2023 00:45:48 +0300 Subject: [PATCH 050/480] Bump version --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 499e7d3b5..321ff4966 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.14.0' +release = '4.14.1' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index 99a734c84..d06b2f7a7 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.14.0' +__version__ = '4.14.1' From 430e3273c86d3c0be48d0276b1f159507e89660b Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 18:25:43 +0500 Subject: [PATCH 051/480] Start of bot API Update - 7.0 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d49ff2e7..289e38d7a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 6.9! +##

Supported Bot API version: 7.0!

Official documentation

Official ru documentation

From 134f45b508aed2ab047a5204a8b0a4071b15b541 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:02:45 +0500 Subject: [PATCH 052/480] Added the classes ReactionTypeEmoji and ReactionTypeCustomEmoji representing different types of reaction. --- telebot/types.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 73efd5592..8c095ef40 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7835,3 +7835,90 @@ def de_json(cls, json_string): def __init__(self) -> None: pass +# base class +class ReactionType(JsonDeserializable, Dictionaryable, JsonSerializable): + """ + This object represents a reaction type. + + Telegram documentation: https://core.telegram.org/bots/api#reactiontype + + :param type: Type of the reaction + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`ReactionType` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, type: str) -> None: + self.type: str = type + + def to_dict(self) -> dict: + json_dict = { + 'type': self.type + } + + return json_dict + + def to_json(self) -> str: + return json.dumps(self.to_dict()) + + +class ReactionTypeEmoji(ReactionType): + """ + This object represents an emoji reaction type. + + Telegram documentation: https://core.telegram.org/bots/api#reactiontypeemoji + + :param type: Type of the reaction, must be emoji + :type type: :obj:`str` + + :param emoji: Reaction emoji. List is available on the API doc. + :type emoji: :obj:`str` + + :return: Instance of the class + :rtype: :class:`ReactionTypeEmoji` + """ + + def __init__(self, emoji: str) -> None: + super().__init__('emoji') + self.emoji: str = emoji + + def to_dict(self) -> dict: + json_dict = super().to_dict() + json_dict['emoji'] = self.emoji + + return json_dict + + +class ReactionTypeCustomEmoji(ReactionType): + """ + This object represents a custom emoji reaction type. + + Telegram documentation: https://core.telegram.org/bots/api#reactiontypecustomemoji + + :param type: Type of the reaction, must be custom_emoji + :type type: :obj:`str` + + :param custom_emoji: Identifier of the custom emoji + :type custom_emoji: :obj:`str` + + :return: Instance of the class + :rtype: :class:`ReactionTypeCustomEmoji` + """ + + def __init__(self, custom_emoji: str) -> None: + super().__init__('custom_emoji') + self.custom_emoji: str = custom_emoji + + def to_dict(self) -> dict: + json_dict = super().to_dict() + json_dict['custom_emoji'] = self.custom_emoji + + return json_dict \ No newline at end of file From 974395ec9bc15a643afeafa3fca9ff14762df675 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:23:47 +0500 Subject: [PATCH 053/480] New handler: message_reaction_handler(untested) --- telebot/__init__.py | 66 ++++++++++++++++++++++++++++++++++++++++ telebot/async_telebot.py | 66 ++++++++++++++++++++++++++++++++++++++++ telebot/types.py | 59 +++++++++++++++++++++++++++++++++-- telebot/util.py | 2 +- 4 files changed, 190 insertions(+), 3 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4a4324507..10cce6761 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -217,6 +217,7 @@ def __init__( self.edited_message_handlers = [] self.channel_post_handlers = [] self.edited_channel_post_handlers = [] + self.message_reaction_handlers = [] self.inline_handlers = [] self.chosen_inline_handlers = [] self.callback_query_handlers = [] @@ -670,6 +671,7 @@ def process_new_updates(self, updates: List[types.Update]): new_edited_messages = None new_channel_posts = None new_edited_channel_posts = None + new_message_reactions = None new_inline_queries = None new_chosen_inline_results = None new_callback_queries = None @@ -737,6 +739,9 @@ def process_new_updates(self, updates: List[types.Update]): if update.chat_join_request: if new_chat_join_request is None: new_chat_join_request = [] new_chat_join_request.append(update.chat_join_request) + if update.message_reactions: + if new_message_reactions is None: new_message_reactions = [] + new_message_reactions.append(update.message_reaction) if new_messages: self.process_new_messages(new_messages) @@ -766,6 +771,8 @@ def process_new_updates(self, updates: List[types.Update]): self.process_new_chat_member(new_chat_members) if new_chat_join_request: self.process_new_chat_join_request(new_chat_join_request) + if new_message_reactions: + self.process_new_message_reaction(new_message_reactions) def process_new_messages(self, new_messages): """ @@ -794,6 +801,12 @@ def process_new_edited_channel_posts(self, edited_channel_post): """ self._notify_command_handlers(self.edited_channel_post_handlers, edited_channel_post, 'edited_channel_post') + def process_new_message_reaction(self, message_reactions): + """ + :meta private: + """ + self._notify_command_handlers(self.message_reaction_handlers, message_reactions, 'message_reaction') + def process_new_inline_query(self, new_inline_queries): """ :meta private: @@ -6174,6 +6187,59 @@ def register_edited_channel_post_handler(self, callback: Callable, content_types **kwargs) self.add_edited_channel_post_handler(handler_dict) + + def message_reaction_handler(self, func, **kwargs): + """ + Handles new incoming message reaction. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_message_reaction_handler(handler_dict) + return handler + + return decorator + + def add_message_reaction_handler(self, handler_dict): + """ + Adds message reaction handler + Note that you should use register_message_reaction_handler to add message_reaction_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.message_reaction_handlers.append(handler_dict) + + def register_message_reaction_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers message reaction handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_message_reaction_handler(handler_dict) + + def inline_handler(self, func, **kwargs): """ Handles new incoming inline query. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 92748a9fc..2c1ff2f3d 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -159,6 +159,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.edited_message_handlers = [] self.channel_post_handlers = [] self.edited_channel_post_handlers = [] + self.message_reaction_handlers = [] self.inline_handlers = [] self.chosen_inline_handlers = [] self.callback_query_handlers = [] @@ -576,6 +577,7 @@ async def process_new_updates(self, updates: List[types.Update]): new_edited_messages = None new_channel_posts = None new_edited_channel_posts = None + new_message_reactions = None new_inline_queries = None new_chosen_inline_results = None new_callback_queries = None @@ -630,6 +632,9 @@ async def process_new_updates(self, updates: List[types.Update]): if update.chat_join_request: if chat_join_request is None: chat_join_request = [] chat_join_request.append(update.chat_join_request) + if update.message_reaction: + if new_message_reactions is None: new_message_reactions = [] + new_message_reactions.append(update.message_reaction) if new_messages: await self.process_new_messages(new_messages) @@ -659,6 +664,8 @@ async def process_new_updates(self, updates: List[types.Update]): await self.process_new_chat_member(new_chat_members) if chat_join_request: await self.process_chat_join_request(chat_join_request) + if new_message_reactions: + await self.process_new_message_reaction(new_message_reactions) async def process_new_messages(self, new_messages): """ @@ -685,6 +692,12 @@ async def process_new_edited_channel_posts(self, edited_channel_post): """ await self._process_updates(self.edited_channel_post_handlers, edited_channel_post, 'edited_channel_post') + async def process_new_message_reaction(self, message_reaction): + """ + :meta private: + """ + await self._process_updates(self.message_reaction_handlers, message_reaction, 'message_reaction') + async def process_new_inline_query(self, new_inline_queries): """ :meta private: @@ -1346,6 +1359,59 @@ def register_edited_channel_post_handler(self, callback: Callable[[Any], Awaitab **kwargs) self.add_edited_channel_post_handler(handler_dict) + def messsage_reaction_handler(self, func, **kwargs): + """ + Handles new incoming message reaction. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: + """ + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_message_reaction_handler(handler_dict) + return handler + + return decorator + + def add_message_reaction_handler(self, handler_dict): + """ + Adds message reaction handler. + Note that you should use register_message_reaction_handler to add message_reaction_handler. + + :meta private: + + :param handler_dict: + :return: + """ + self.message_reaction_handlers.append(handler_dict) + + def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable], func: Callable, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers message reaction handler. + + :param callback: function to be called + :type callback: :obj:`Awaitable` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_message_reaction_handler(handler_dict) + + def inline_handler(self, func, **kwargs): """ Handles new incoming inline query. diff --git a/telebot/types.py b/telebot/types.py index 8c095ef40..976643e92 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -127,6 +127,10 @@ class Update(JsonDeserializable): :param edited_channel_post: Optional. New version of a channel post that is known to the bot and was edited :type edited_channel_post: :class:`telebot.types.Message` + :param message_reaction: 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. + :type message_reaction: :class:`telebot.types.MessageReactionUpdated` + :param inline_query: Optional. New incoming inline query :type inline_query: :class:`telebot.types.InlineQuery` @@ -188,13 +192,14 @@ def de_json(cls, json_string): my_chat_member = ChatMemberUpdated.de_json(obj.get('my_chat_member')) chat_member = ChatMemberUpdated.de_json(obj.get('chat_member')) chat_join_request = ChatJoinRequest.de_json(obj.get('chat_join_request')) + message_reaction = MessageReactionUpdated.de_json(obj.get('message_reaction')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request): + my_chat_member, chat_member, chat_join_request, message_reaction): self.update_id = update_id self.message = message self.edited_message = edited_message @@ -210,6 +215,7 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.my_chat_member = my_chat_member self.chat_member = chat_member self.chat_join_request = chat_join_request + self.message_reaction = message_reaction class ChatMemberUpdated(JsonDeserializable): @@ -7921,4 +7927,53 @@ def to_dict(self) -> dict: json_dict = super().to_dict() json_dict['custom_emoji'] = self.custom_emoji - return json_dict \ No newline at end of file + return json_dict + + +class MessageReactionUpdated(JsonDeserializable): + """ + This object represents a service message about a change in the list of the current user's reactions to a message. + + Telegram documentation: https://core.telegram.org/bots/api#messagereactionupdated + + :param chat: The chat containing the message the user reacted to + :type chat: :class:`telebot.types.Chat` + + :param message_id: Unique identifier of the message inside the chat + :type message_id: :obj:`int` + + :param user: Optional. The user that changed the reaction, if the user isn't anonymous + :type user: :class:`telebot.types.User` + + :param actor_chat: Optional. The chat on behalf of which the reaction was changed, if the user is anonymous + :type actor_chat: :class:`telebot.types.Chat` + + :param date: Date of the change in Unix time + :type date: :obj:`int` + + :param old_reaction: Previous list of reaction types that were set by the user + :type old_reaction: :obj:`list` of :class:`ReactionType` + + :param new_reaction: New list of reaction types that have been set by the user + :type new_reaction: :obj:`list` of :class:`ReactionType` + + :return: Instance of the class + :rtype: :class:`MessageReactionUpdated` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, chat: Chat, message_id: int, date: int, old_reaction: List[ReactionType], new_reaction: List[ReactionType], + user: Optional[User]=None, actor_chat: Optional[Chat]=None) -> None: + self.chat: Chat = chat + self.message_id: int = message_id + self.user: Optional[User] = user + self.actor_chat: Optional[Chat] = actor_chat + self.date: int = date + self.old_reaction: List[ReactionType] = old_reaction + self.new_reaction: List[ReactionType] = new_reaction \ No newline at end of file diff --git a/telebot/util.py b/telebot/util.py index 88fb4db96..1c0d06c5a 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -45,7 +45,7 @@ update_types = [ "message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member", - "chat_join_request", + "chat_join_request", "message_reaction" ] From 8fee13649079014242826bb11144fbc51ab31f7d Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:28:47 +0500 Subject: [PATCH 054/480] Fix tests for the new handler --- tests/test_handler_backends.py | 6 ++++-- tests/test_telebot.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index 21cf8f9b2..52b84d352 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -65,9 +65,10 @@ def update_type(message): my_chat_member = None chat_member = None chat_join_request = None + message_reaction = None return types.Update(1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request) + my_chat_member, chat_member, chat_join_request, message_reaction) @pytest.fixture() @@ -85,9 +86,10 @@ def reply_to_message_update_type(reply_to_message): my_chat_member = None chat_member = None chat_join_request = None + message_reaction = None return types.Update(1001234038284, reply_to_message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, - poll, poll_answer, my_chat_member, chat_member, chat_join_request) + poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction) def next_handler(message): diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 280a19f7c..4b7b78a61 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -542,9 +542,10 @@ def create_message_update(text): my_chat_member = None chat_member = None chat_join_request = None + message_reaction = None return types.Update(-1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request) + my_chat_member, chat_member, chat_join_request, message_reaction) def test_is_string_unicode(self): s1 = u'string' From 97e0d4e180e36408af5aab24f1c1da68c279541e Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:36:52 +0500 Subject: [PATCH 055/480] Fix tests #2 --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 976643e92..a1257e792 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -195,7 +195,7 @@ def de_json(cls, json_string): message_reaction = MessageReactionUpdated.de_json(obj.get('message_reaction')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request) + my_chat_member, chat_member, chat_join_request, message_reaction) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, From 2fb2e30eeaf83febe6af0dceb8cb11e274e90436 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:38:11 +0500 Subject: [PATCH 056/480] Fix minor issue for tests #3 --- telebot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 10cce6761..f9c1c7d52 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -739,7 +739,7 @@ def process_new_updates(self, updates: List[types.Update]): if update.chat_join_request: if new_chat_join_request is None: new_chat_join_request = [] new_chat_join_request.append(update.chat_join_request) - if update.message_reactions: + if update.message_reaction: if new_message_reactions is None: new_message_reactions = [] new_message_reactions.append(update.message_reaction) From 854c68530eb47ef72e03fdea04be4803d6536400 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:53:39 +0500 Subject: [PATCH 057/480] Added updates about reaction changes on a message with anonymous reactions, represented by the class MessageReactionCountUpdated and the field message_reaction_count in the class Update. The bot must explicitly allow the update to receive it. --- telebot/__init__.py | 63 ++++++++++++++++++++++++++++++++ telebot/async_telebot.py | 66 ++++++++++++++++++++++++++++++++++ telebot/types.py | 78 ++++++++++++++++++++++++++++++++++++++-- telebot/util.py | 2 +- 4 files changed, 205 insertions(+), 4 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index f9c1c7d52..366ad70d1 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -218,6 +218,7 @@ def __init__( self.channel_post_handlers = [] self.edited_channel_post_handlers = [] self.message_reaction_handlers = [] + self.message_reaction_count_handlers = [] self.inline_handlers = [] self.chosen_inline_handlers = [] self.callback_query_handlers = [] @@ -672,6 +673,7 @@ def process_new_updates(self, updates: List[types.Update]): new_channel_posts = None new_edited_channel_posts = None new_message_reactions = None + message_reaction_counts = None new_inline_queries = None new_chosen_inline_results = None new_callback_queries = None @@ -742,6 +744,9 @@ def process_new_updates(self, updates: List[types.Update]): if update.message_reaction: if new_message_reactions is None: new_message_reactions = [] new_message_reactions.append(update.message_reaction) + if update.message_reaction_count: + if message_reaction_counts is None: message_reaction_counts = [] + message_reaction_counts.append(update.message_reaction_count) if new_messages: self.process_new_messages(new_messages) @@ -773,6 +778,8 @@ def process_new_updates(self, updates: List[types.Update]): self.process_new_chat_join_request(new_chat_join_request) if new_message_reactions: self.process_new_message_reaction(new_message_reactions) + if message_reaction_counts: + self.process_new_message_reaction_count(message_reaction_counts) def process_new_messages(self, new_messages): """ @@ -806,6 +813,12 @@ def process_new_message_reaction(self, message_reactions): :meta private: """ self._notify_command_handlers(self.message_reaction_handlers, message_reactions, 'message_reaction') + + def process_new_message_reaction_count(self, message_reaction_counts): + """ + :meta private: + """ + self._notify_command_handlers(self.message_reaction_count_handlers, message_reaction_counts, 'message_reaction_count') def process_new_inline_query(self, new_inline_queries): """ @@ -6239,6 +6252,56 @@ def register_message_reaction_handler(self, callback: Callable, func: Callable, handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_message_reaction_handler(handler_dict) + def message_reaction_count_handler(self, func, **kwargs): + """ + Handles new incoming message reaction count. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_message_reaction_count_handler(handler_dict) + return handler + + return decorator + + def add_message_reaction_count_handler(self, handler_dict): + """ + Adds message reaction count handler + Note that you should use register_message_reaction_count_handler to add message_reaction_count_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.message_reaction_count_handlers.append(handler_dict) + + def register_message_reaction_count_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers message reaction count handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_message_reaction_count_handler(handler_dict) def inline_handler(self, func, **kwargs): """ diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 2c1ff2f3d..a6fdf5cd6 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -160,6 +160,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.channel_post_handlers = [] self.edited_channel_post_handlers = [] self.message_reaction_handlers = [] + self.message_reaction_count_handlers = [] self.inline_handlers = [] self.chosen_inline_handlers = [] self.callback_query_handlers = [] @@ -578,6 +579,7 @@ async def process_new_updates(self, updates: List[types.Update]): new_channel_posts = None new_edited_channel_posts = None new_message_reactions = None + mew_message_reaction_count_handlers = None new_inline_queries = None new_chosen_inline_results = None new_callback_queries = None @@ -635,6 +637,10 @@ async def process_new_updates(self, updates: List[types.Update]): if update.message_reaction: if new_message_reactions is None: new_message_reactions = [] new_message_reactions.append(update.message_reaction) + if update.message_reaction_count: + if new_message_reaction_count_handlers is None: new_message_reaction_count_handlers = [] + new_message_reaction_count_handlers.append(update.message_reaction_count) + if new_messages: await self.process_new_messages(new_messages) @@ -666,6 +672,8 @@ async def process_new_updates(self, updates: List[types.Update]): await self.process_chat_join_request(chat_join_request) if new_message_reactions: await self.process_new_message_reaction(new_message_reactions) + if new_message_reaction_count_handlers: + await self.process_new_message_reaction_count(new_message_reaction_count_handlers) async def process_new_messages(self, new_messages): """ @@ -698,6 +706,12 @@ async def process_new_message_reaction(self, message_reaction): """ await self._process_updates(self.message_reaction_handlers, message_reaction, 'message_reaction') + async def process_new_message_reaction_count(self, message_reaction_count): + """ + :meta private: + """ + await self._process_updates(self.message_reaction_count_handlers, message_reaction_count, 'message_reaction_count') + async def process_new_inline_query(self, new_inline_queries): """ :meta private: @@ -1411,6 +1425,58 @@ def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable] handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_message_reaction_handler(handler_dict) + def message_reaction_count_handler(self, func, **kwargs): + """ + Handles new incoming message reaction count. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: + """ + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_message_reaction_count_handler(handler_dict) + return handler + + return decorator + + def add_message_reaction_count_handler(self, handler_dict): + """ + Adds message reaction count handler + Note that you should use register_message_reaction_count_handler to add message_reaction_count_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.message_reaction_count_handlers.append(handler_dict) + + def register_message_reaction_count_handler(self, callback: Callable[[Any], Awaitable], func: Callable, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers message reaction count handler. + + :param callback: function to be called + :type callback: :obj:`Awaitable` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_message_reaction_count_handler(handler_dict) + def inline_handler(self, func, **kwargs): """ diff --git a/telebot/types.py b/telebot/types.py index a1257e792..72f2558a2 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -131,6 +131,10 @@ class Update(JsonDeserializable): 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. :type message_reaction: :class:`telebot.types.MessageReactionUpdated` + :param message_reaction_count: 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. + :type message_reaction_count: :class:`telebot.types.MessageReactionCountUpdated` + :param inline_query: Optional. New incoming inline query :type inline_query: :class:`telebot.types.InlineQuery` @@ -193,13 +197,14 @@ def de_json(cls, json_string): chat_member = ChatMemberUpdated.de_json(obj.get('chat_member')) chat_join_request = ChatJoinRequest.de_json(obj.get('chat_join_request')) message_reaction = MessageReactionUpdated.de_json(obj.get('message_reaction')) + message_reaction_count = MessageReactionCountUpdated.de_json(obj.get('message_reaction_count')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction): + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count): self.update_id = update_id self.message = message self.edited_message = edited_message @@ -216,6 +221,7 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.chat_member = chat_member self.chat_join_request = chat_join_request self.message_reaction = message_reaction + self.message_reaction_count = message_reaction_count class ChatMemberUpdated(JsonDeserializable): @@ -7976,4 +7982,70 @@ def __init__(self, chat: Chat, message_id: int, date: int, old_reaction: List[Re self.actor_chat: Optional[Chat] = actor_chat self.date: int = date self.old_reaction: List[ReactionType] = old_reaction - self.new_reaction: List[ReactionType] = new_reaction \ No newline at end of file + self.new_reaction: List[ReactionType] = new_reaction + + + +class MessageReactionCountUpdated(JsonDeserializable): + """ + This object represents a service message about a change in the list of the current user's reactions to a message. + + Telegram documentation: https://core.telegram.org/bots/api#messagereactioncountupdated + + :param chat: The chat containing the message + :type chat: :class:`telebot.types.Chat` + + :param message_id: Unique message identifier inside the chat + :type message_id: :obj:`int` + + :param date: Date of the change in Unix time + :type date: :obj:`int` + + :param reactions: List of reactions that are present on the message + :type reactions: :obj:`list` of :class:`ReactionCount` + + :return: Instance of the class + :rtype: :class:`MessageReactionCountUpdated` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[ReactionCount]) -> None: + self.chat: Chat = chat + self.message_id: int = message_id + self.date: int = date + self.reactions: List[ReactionCount] = reactions + + +class ReactionCount(JsonDeserializable): + """ + This object represents a reaction added to a message along with the number of times it was added. + + Telegram documentation: https://core.telegram.org/bots/api#reactioncount + + :param type: Type of the reaction + :type type: :class:`ReactionType` + + :param total_count: Number of times the reaction was added + :type total_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`ReactionCount` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, type: ReactionType, total_count: int) -> None: + self.type: ReactionType = type + self.total_count: int = total_count + diff --git a/telebot/util.py b/telebot/util.py index 1c0d06c5a..174239d35 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -45,7 +45,7 @@ update_types = [ "message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member", - "chat_join_request", "message_reaction" + "chat_join_request", "message_reaction", "message_reaction_count" ] From 96b4ced7788b8f397cf7586cd0404d3e1a136bc1 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 19:54:51 +0500 Subject: [PATCH 058/480] Fix tests for the new handler --- tests/test_handler_backends.py | 6 ++++-- tests/test_telebot.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index 52b84d352..ef22e8520 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -66,9 +66,10 @@ def update_type(message): chat_member = None chat_join_request = None message_reaction = None + message_reaction_count = None return types.Update(1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) @pytest.fixture() @@ -87,9 +88,10 @@ def reply_to_message_update_type(reply_to_message): chat_member = None chat_join_request = None message_reaction = None + message_reaction_count = None return types.Update(1001234038284, reply_to_message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, - poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction) + poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) def next_handler(message): diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 4b7b78a61..c1f08f8f0 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -543,9 +543,10 @@ def create_message_update(text): chat_member = None chat_join_request = None message_reaction = None + message_reaction_count = None return types.Update(-1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) def test_is_string_unicode(self): s1 = u'string' From b6a0d6caa56db1fba085c18a9b7a2a7c7d7407a5 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 21:14:36 +0500 Subject: [PATCH 059/480] Added the method setMessageReaction that allows bots to react to messages. --- telebot/__init__.py | 23 +++++++++++++++++++++++ telebot/apihelper.py | 10 ++++++++++ telebot/async_telebot.py | 24 ++++++++++++++++++++++++ telebot/asyncio_helper.py | 9 +++++++++ 4 files changed, 66 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 366ad70d1..23a95eea4 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1329,6 +1329,29 @@ def close(self) -> bool: :return: :obj:`bool` """ return apihelper.close(self.token) + + def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: + """ + Use this method to set a reaction to a message in a chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setmessagereaction + + :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Identifier of the message to set reaction to + :type message_id: :obj:`int` + + :param reaction: New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message. + A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators. + :type reaction: :obj:`list` of :class:`telebot.types.ReactionType` + + :param is_big: Pass True to set the reaction with a big animation + :type is_big: :obj:`bool` + + :return: :obj:`bool` + """ + return apihelper.set_message_reaction(self.token, chat_id, message_id, reaction, is_big) def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index bfee49967..8ae65814f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -332,6 +332,16 @@ def get_user_profile_photos(token, user_id, offset=None, limit=None): payload['limit'] = limit return _make_request(token, method_url, params=payload) +def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None): + method_url = r'setMessageReaction' + payload = {'chat_id': chat_id, 'message_id': message_id} + if reaction: + payload['reaction'] = reaction + if is_big is not None: + payload['is_big'] = is_big + return _make_request(token, method_url, params=payload) + + def get_chat(token, chat_id): method_url = r'getChat' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index a6fdf5cd6..0f630ca5d 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2297,6 +2297,30 @@ async def get_webhook_info(self, timeout: Optional[int]=None) -> types.WebhookIn result = await asyncio_helper.get_webhook_info(self.token, timeout) return types.WebhookInfo.de_json(result) + async def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: + """ + Use this method to set a reaction to a message in a chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setmessagereaction + + :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Identifier of the message to set reaction to + :type message_id: :obj:`int` + + :param reaction: New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message. + A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators. + :type reaction: :obj:`list` of :class:`telebot.types.ReactionType` + + :param is_big: Pass True to set the reaction with a big animation + :type is_big: :obj:`bool` + + :return: :obj:`bool` + """ + result = await asyncio_helper.set_message_reaction(self.token, chat_id, message_id, reaction, is_big) + return result + async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, limit: Optional[int]=None) -> types.UserProfilePhotos: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 526166eec..91538abc4 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -318,6 +318,15 @@ async def get_user_profile_photos(token, user_id, offset=None, limit=None): payload['limit'] = limit return await _process_request(token, method_url, params=payload) +async def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None): + method_url = r'setMessageReaction' + payload = {'chat_id': chat_id, 'message_id': message_id} + if reaction: + payload['reaction'] = reaction + if is_big is not None: + payload['is_big'] = is_big + return await _process_request(token, method_url, params=payload) + async def get_chat(token, chat_id): method_url = r'getChat' From 75764586ce97087d3c56ace1060e6489424707f9 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 21:20:15 +0500 Subject: [PATCH 060/480] Added the field available_reactions to the class Chat. --- telebot/types.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 72f2558a2..0f0e5f00e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -551,6 +551,10 @@ class Chat(JsonDeserializable): Returned only in getChat. :type active_usernames: :obj:`list` of :obj:`str` + :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels. + Returned only in getChat. + :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType` + :param emoji_status_custom_emoji_id: Optional. Custom emoji identifier of emoji status of the other party in a private chat. Returned only in getChat. :type emoji_status_custom_emoji_id: :obj:`str` @@ -644,6 +648,8 @@ def de_json(cls, json_string): obj['permissions'] = ChatPermissions.de_json(obj['permissions']) if 'location' in obj: obj['location'] = ChatLocation.de_json(obj['location']) + if 'available_reactions' in obj: + obj['available_reactions'] = [ReactionType(reaction) for reaction in obj['available_reactions']] return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -654,7 +660,8 @@ def __init__(self, id, type, title=None, username=None, first_name=None, can_set_sticker_set=None, linked_chat_id=None, location=None, join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, - has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, **kwargs): + has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, + available_reactions=None,**kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -684,6 +691,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.has_hidden_members: bool = has_hidden_members self.has_aggressive_anti_spam_enabled: bool = has_aggressive_anti_spam_enabled self.emoji_status_expiration_date: int = emoji_status_expiration_date + self.available_reactions: List[ReactionType] = available_reactions class MessageID(JsonDeserializable): From ad816f2c3fd8f9cd70c6e4dd5b08585566104a78 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 21:42:30 +0500 Subject: [PATCH 061/480] Added the class ExternalReplyInfo and the field external_reply of type ExternalReplyInfo to the class Message, containing information about a message that is replied to by the current message, but can be from another chat or forum topic. --- telebot/types.py | 511 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 511 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 0f0e5f00e..700911f50 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8057,3 +8057,514 @@ def __init__(self, type: ReactionType, total_count: int) -> None: self.type: ReactionType = type self.total_count: int = total_count + + +class ExternalReplyInfo(JsonDeserializable): + """ + This object contains information about a message that is being replied to, + which may come from another chat or forum topic. + + Telegram documentation: https://core.telegram.org/bots/api#externalreplyinfo + + :param origin: Origin of the message replied to by the given message + :type origin: :class:`MessageOrigin` + + :param chat: Optional. Chat the original message belongs to. Available only if the chat is a supergroup or a channel. + :type chat: :class:`Chat` + + :param message_id: Optional. Unique message identifier inside the original chat. Available only if the original chat is a supergroup or a channel. + :type message_id: :obj:`int` + + :param link_preview_options: Optional. Options used for link preview generation for the original message, if it is a text message + :type link_preview_options: :class:`LinkPreviewOptions` + + :param animation: Optional. Message is an animation, information about the animation + :type animation: :class:`Animation` + + :param audio: Optional. Message is an audio file, information about the file + :type audio: :class:`Audio` + + :param document: Optional. Message is a general file, information about the file + :type document: :class:`Document` + + :param photo: Optional. Message is a photo, available sizes of the photo + :type photo: :obj:`list` of :class:`PhotoSize` + + :param sticker: Optional. Message is a sticker, information about the sticker + :type sticker: :class:`Sticker` + + :param story: Optional. Message is a forwarded story + :type story: :class:`Story` + + :param video: Optional. Message is a video, information about the video + :type video: :class:`Video` + + :param video_note: Optional. Message is a video note, information about the video message + :type video_note: :class:`VideoNote` + + :param voice: Optional. Message is a voice message, information about the file + :type voice: :class:`Voice` + + :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation + :type has_media_spoiler: :obj:`bool` + + :param contact: Optional. Message is a shared contact, information about the contact + :type contact: :class:`Contact` + + :param dice: Optional. Message is a dice with random value + :type dice: :class:`Dice` + + :param game: Optional. Message is a game, information about the game. More about games » + :type game: :class:`Game` + + :param giveaway: Optional. Message is a scheduled giveaway, information about the giveaway + :type giveaway: :class:`Giveaway` + + :param giveaway_winners: Optional. A giveaway with public winners was completed + :type giveaway_winners: :class:`GiveawayWinners` + + :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » + :type invoice: :class:`Invoice` + + :param location: Optional. Message is a shared location, information about the location + :type location: :class:`Location` + + :param poll: Optional. Message is a native poll, information about the poll + :type poll: :class:`Poll` + + :param venue: Optional. Message is a venue, information about the venue + :type venue: :class:`Venue` + + :return: Instance of the class + :rtype: :class:`ExternalReplyInfo` + """ + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + origin = obj.get('origin') + if origin is not None: + origin = MessageOrigin.de_json(origin) + + chat = obj.get('chat') + if chat is not None: + chat = Chat.de_json(chat) + + message_id = obj.get('message_id') + if message_id is not None: + message_id = int(message_id) + + link_preview_options = obj.get('link_preview_options') + if link_preview_options is not None: + link_preview_options = LinkPreviewOptions.de_json(link_preview_options) + + animation = obj.get('animation') + if animation is not None: + animation = Animation.de_json(animation) + + audio = obj.get('audio') + if audio is not None: + audio = Audio.de_json(audio) + + document = obj.get('document') + if document is not None: + document = Document.de_json(document) + + photo = obj.get('photo') + if photo is not None: + photo = [PhotoSize.de_json(photo[i]) for i in range(len(photo))] + + sticker = obj.get('sticker') + if sticker is not None: + sticker = Sticker.de_json(sticker) + + story = obj.get('story') + if story is not None: + story = Story.de_json(story) + + video = obj.get('video') + if video is not None: + video = Video.de_json(video) + + video_note = obj.get('video_note') + if video_note is not None: + video_note = VideoNote.de_json(video_note) + + voice = obj.get('voice') + if voice is not None: + voice = Voice.de_json(voice) + + has_media_spoiler = obj.get('has_media_spoiler') + if has_media_spoiler is not None: + has_media_spoiler = bool(has_media_spoiler) + + contact = obj.get('contact') + if contact is not None: + contact = Contact.de_json(contact) + + dice = obj.get('dice') + if dice is not None: + dice = Dice.de_json(dice) + + game = obj.get('game') + if game is not None: + game = Game.de_json(game) + + giveaway = obj.get('giveaway') + if giveaway is not None: + giveaway = Giveaway.de_json(giveaway) + + giveaway_winners = obj.get('giveaway_winners') + if giveaway_winners is not None: + giveaway_winners = GiveawayWinners.de_json(giveaway_winners) + + invoice = obj.get('invoice') + if invoice is not None: + invoice = Invoice.de_json(invoice) + + location = obj.get('location') + if location is not None: + location = Location.de_json(location) + + poll = obj.get('poll') + if poll is not None: + poll = Poll.de_json(poll) + + venue = obj.get('venue') + if venue is not None: + venue = Venue.de_json(venue) + + return cls(origin=origin, chat=chat, message_id=message_id, link_preview_options=link_preview_options, + animation=animation, audio=audio, document=document, photo=photo, sticker=sticker, story=story, + video=video, video_note=video_note, voice=voice, has_media_spoiler=has_media_spoiler, + contact=contact, dice=dice, game=game, giveaway=giveaway, giveaway_winners=giveaway_winners, + invoice=invoice, location=location, poll=poll, venue=venue) + + def __init__(self, origin: MessageOrigin, chat: Optional[Chat]=None, message_id: Optional[int]=None, + link_preview_options: Optional[LinkPreviewOptions]=None, animation: Optional[Animation]=None, + audio: Optional[Audio]=None, document: Optional[Document]=None, photo: Optional[List[PhotoSize]]=None, + sticker: Optional[Sticker]=None, story: Optional[Story]=None, video: Optional[Video]=None, + video_note: Optional[VideoNote]=None, voice: Optional[Voice]=None, + has_media_spoiler: Optional[bool]=None, contact: Optional[Contact]=None, + dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None, + giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None, + location: Optional[Location]=None, poll: Optional[Poll]=None, + venue: Optional[Venue]=None) -> None: + self.origin: MessageOrigin = origin + + self.chat: Optional[Chat] = chat + self.message_id: Optional[int] = message_id + self.link_preview_options: Optional[LinkPreviewOptions] = link_preview_options + self.animation: Optional[Animation] = animation + self.audio: Optional[Audio] = audio + self.document: Optional[Document] = document + self.photo: Optional[List[PhotoSize]] = photo + self.sticker: Optional[Sticker] = sticker + self.story: Optional[Story] = story + self.video: Optional[Video] = video + self.video_note: Optional[VideoNote] = video_note + self.voice: Optional[Voice] = voice + self.has_media_spoiler: Optional[bool] = has_media_spoiler + self.contact: Optional[Contact] = contact + self.dice: Optional[Dice] = dice + self.game: Optional[Game] = game + self.giveaway: Optional[Giveaway] = giveaway + self.giveaway_winners: Optional[GiveawayWinners] = giveaway_winners + self.invoice: Optional[Invoice] = invoice + self.location: Optional[Location] = location + self.poll: Optional[Poll] = poll + self.venue: Optional[Venue] = venue + +class MessageOrigin(JsonDeserializable): + """ + This object describes the origin of a message. + + Telegram documentation: https://core.telegram.org/bots/api#messageorigin + + :param type: Type of the message origin + :type type: :obj:`str` + + :param date: Date the message was sent originally in Unix time + :type date: :obj:`int` + + :param sender_user: User that sent the message originally (for MessageOriginUser) + :type sender_user: :class:`User` + + :param sender_user_name: Name of the user that sent the message originally (for MessageOriginHiddenUser) + :type sender_user_name: :obj:`str` + + :param sender_chat: Chat that sent the message originally (for MessageOriginChat) + :type sender_chat: :class:`Chat` + + :param author_signature: Optional. Author signature for certain cases + :type author_signature: :obj:`str` + + :return: Instance of the class + :rtype: :class:`MessageOrigin` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + message_type = obj.get('type') + if message_type == 'user': + sender_user = User.de_json(obj.get('sender_user')) + return MessageOriginUser(date=obj.get('date'), sender_user=sender_user) + elif message_type == 'hidden_user': + return MessageOriginHiddenUser(date=obj.get('date'), sender_user_name=obj.get('sender_user_name')) + elif message_type == 'chat': + sender_chat = Chat.de_json(obj.get('sender_chat')) + return MessageOriginChat(date=obj.get('date'), sender_chat=sender_chat, author_signature=obj.get('author_signature')) + elif message_type == 'channel': + chat = Chat.de_json(obj.get('chat')) + return MessageOriginChannel(date=obj.get('date'), chat=chat, message_id=obj.get('message_id'), author_signature=obj.get('author_signature')) + + def __init__(self, type: str, date: int) -> None: + self.type: str = type + self.date: int = date + + +class MessageOriginUser(MessageOrigin): + """ + The message was originally sent by a known user. + + :param sender_user: User that sent the message originally + :type sender_user: :class:`User` + """ + + def __init__(self, date: int, sender_user: Optional[User] = None) -> None: + super().__init__('user', date) + self.sender_user: Optional[User] = sender_user + + +class MessageOriginHiddenUser(MessageOrigin): + """ + The message was originally sent by an unknown user. + + :param sender_user_name: Name of the user that sent the message originally + :type sender_user_name: :obj:`str` + """ + + def __init__(self, date: int, sender_user_name: Optional[str] = None) -> None: + super().__init__('hidden_user', date) + self.sender_user_name: Optional[str] = sender_user_name + + +class MessageOriginChat(MessageOrigin): + """ + The message was originally sent on behalf of a chat to a group chat. + + :param sender_chat: Chat that sent the message originally + :type sender_chat: :class:`Chat` + + :param author_signature: Optional. For messages originally sent by an anonymous chat administrator, original message author signature + :type author_signature: :obj:`str` + """ + + def __init__(self, date: int, sender_chat: Optional[Chat] = None, author_signature: Optional[str] = None) -> None: + super().__init__('chat', date) + self.sender_chat: Optional[Chat] = sender_chat + self.author_signature: Optional[str] = author_signature + + +class MessageOriginChannel(MessageOrigin): + """ + The message was originally sent to a channel chat. + + :param chat: Channel chat to which the message was originally sent + :type chat: :class:`Chat` + + :param message_id: Unique message identifier inside the chat + :type message_id: :obj:`int` + + :param author_signature: Optional. Signature of the original post author + :type author_signature: :obj:`str` + """ + + def __init__(self, date: int, chat: Optional[Chat] = None, message_id: Optional[int] = None, author_signature: Optional[str] = None) -> None: + super().__init__('channel', date) + self.chat: Optional[Chat] = chat + self.message_id: Optional[int] = message_id + self.author_signature: Optional[str] = author_signature + + +class LinkPreviewOptions(JsonDeserializable): + """ + Describes the options used for link preview generation. + + Telegram documentation: https://core.telegram.org/bots/api#linkpreviewoptions + + :param is_disabled: Optional. True, if the link preview is disabled + :type is_disabled: :obj:`bool` + + :param url: Optional. URL to use for the link preview. If empty, then the first URL found in the message text will be used + :type url: :obj:`str` + + :param prefer_small_media: Optional. True, if the media in the link preview is supposed to be shrunk; ignored if the URL isn't explicitly specified or media size change isn't supported for the preview + :type prefer_small_media: :obj:`bool` + + :param prefer_large_media: Optional. True, if the media in the link preview is supposed to be enlarged; ignored if the URL isn't explicitly specified or media size change isn't supported for the preview + :type prefer_large_media: :obj:`bool` + + :param show_above_text: Optional. True, if the link preview must be shown above the message text; otherwise, the link preview will be shown below the message text + :type show_above_text: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`LinkPreviewOptions` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + return cls(is_disabled=obj.get('is_disabled'), url=obj.get('url'), prefer_small_media=obj.get('prefer_small_media'), + prefer_large_media=obj.get('prefer_large_media'), show_above_text=obj.get('show_above_text')) + + + def __init__(self, is_disabled: Optional[bool] = None, url: Optional[str] = None, + prefer_small_media: Optional[bool] = None, prefer_large_media: Optional[bool] = None, + show_above_text: Optional[bool] = None) -> None: + self.is_disabled: Optional[bool] = is_disabled + self.url: Optional[str] = url + self.prefer_small_media: Optional[bool] = prefer_small_media + self.prefer_large_media: Optional[bool] = prefer_large_media + self.show_above_text: Optional[bool] = show_above_text + + +class Giveaway(JsonDeserializable): + """ + This object represents a message about a scheduled giveaway. + + Telegram documentation: https://core.telegram.org/bots/api#giveaway + + :param chats: The list of chats which the user must join to participate in the giveaway + :type chats: :obj:`list` of :class:`Chat` + + :param winners_selection_date: Point in time (Unix timestamp) when winners of the giveaway will be selected + :type winners_selection_date: :obj:`int` + + :param winner_count: The number of users which are supposed to be selected as winners of the giveaway + :type winner_count: :obj:`int` + + :param only_new_members: Optional. True, if only users who join the chats after the giveaway started should be eligible to win + :type only_new_members: :obj:`bool` + + :param has_public_winners: Optional. True, if the list of giveaway winners will be visible to everyone + :type has_public_winners: :obj:`bool` + + :param prize_description: Optional. Description of additional giveaway prize + :type prize_description: :obj:`str` + + :param country_codes: Optional. A list of two-letter ISO 3166-1 alpha-2 country codes indicating the countries from which eligible users for the giveaway must come. If empty, then all users can participate in the giveaway. + :type country_codes: :obj:`list` of :obj:`str` + + :param premium_subscription_month_count: Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for + :type premium_subscription_month_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`Giveaway` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + chats = [Chat.de_json(chat) for chat in obj.get('chats', [])] + + return cls(**obj, chats=chats) + + def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: int, + only_new_members: Optional[bool] = None, has_public_winners: Optional[bool] = None, + prize_description: Optional[str] = None, country_codes: Optional[List[str]] = None, + premium_subscription_month_count: Optional[int] = None) -> None: + self.chats: List[Chat] = chats + self.winners_selection_date: int = winners_selection_date + self.winner_count: int = winner_count + self.only_new_members: Optional[bool] = only_new_members + self.has_public_winners: Optional[bool] = has_public_winners + self.prize_description: Optional[str] = prize_description + self.country_codes: Optional[List[str]] = country_codes or [] + self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count + +class GiveawayWinners(JsonDeserializable): + """ + This object represents a message about the completion of a giveaway with public winners. + + Telegram documentation: https://core.telegram.org/bots/api#giveawaywinners + + :param chat: The chat that created the giveaway + :type chat: :class:`Chat` + + :param giveaway_message_id: Identifier of the messsage with the giveaway in the chat + :type giveaway_message_id: :obj:`int` + + :param winners_selection_date: Point in time (Unix timestamp) when winners of the giveaway were selected + :type winners_selection_date: :obj:`int` + + :param winner_count: Total number of winners in the giveaway + :type winner_count: :obj:`int` + + :param winners: List of up to 100 winners of the giveaway + :type winners: :obj:`list` of :class:`User` + + :param additional_chat_count: Optional. The number of other chats the user had to join in order to be eligible for the giveaway + :type additional_chat_count: :obj:`int` + + :param premium_subscription_month_count: Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for + :type premium_subscription_month_count: :obj:`int` + + :param unclaimed_prize_count: Optional. Number of undistributed prizes + :type unclaimed_prize_count: :obj:`int` + + :param only_new_members: Optional. True, if only users who had joined the chats after the giveaway started were eligible to win + :type only_new_members: :obj:`bool` + + :param was_refunded: Optional. True, if the giveaway was canceled because the payment for it was refunded + :type was_refunded: :obj:`bool` + + :param prize_description: Optional. Description of additional giveaway prize + :type prize_description: :obj:`str` + + :return: Instance of the class + :rtype: :class:`GiveawayWinners` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + obj['chat'] = Chat.de_json(obj.get('chat')) + obj['winners'] = [User.de_json(user) for user in obj.get('winners', [])] + + return cls(**obj) + + def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: int, winner_count: int, + winners: List[User], additional_chat_count: Optional[int] = None, + premium_subscription_month_count: Optional[int] = None, unclaimed_prize_count: Optional[int] = None, + only_new_members: Optional[bool] = None, was_refunded: Optional[bool] = None, + prize_description: Optional[str] = None) -> None: + self.chat: Chat = chat + self.giveaway_message_id: int = giveaway_message_id + self.winners_selection_date: int = winners_selection_date + self.winner_count: int = winner_count + self.winners: List[User] = winners + self.additional_chat_count: Optional[int] = additional_chat_count + self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count + self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count + self.only_new_members: Optional[bool] = only_new_members + self.was_refunded: Optional[bool] = was_refunded + self.prize_description: Optional[str] = prize_description + + + \ No newline at end of file From 5e018918c67ad0765dc505be11575d8ac289aa40 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 21:52:22 +0500 Subject: [PATCH 062/480] Added TextQuote and fixed extrernal_reply (forgot in previous commit); CHECK THE COMMIT! --- telebot/types.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 700911f50..bdb1d290d 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -807,6 +807,12 @@ class Message(JsonDeserializable): will not contain further reply_to_message fields even if it itself is a reply. :type reply_to_message: :class:`telebot.types.Message` + :param external_reply: Optional. Information about the message that is being replied to, which may come from another chat or forum topic + :type external_reply: :class:`telebot.types.ExternalReplyInfo` + + :param quote: Optional. For replies that quote part of the original message, the quoted part of the message + :type quote: :class:`telebot.types.TextQuote` + :param via_bot: Optional. Bot through which the message was sent :type via_bot: :class:`telebot.types.User` @@ -1208,6 +1214,13 @@ def de_json(cls, json_string): if 'story' in obj: opts['story'] = Story.de_json(obj['story']) content_type = 'story' + if 'external_reply' in obj: + opts['external_reply'] = ExternalReplyInfo.de_json(obj['external_reply']) + content_type = 'text' # @Badiboy not sure about content_types in here, please check + if 'quote' in obj: + opts['quote'] = TextQuote.de_json(obj['quote']) + content_type = 'text' # Here too, check the content types + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod @@ -1306,6 +1319,9 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.user_shared: Optional[UserShared] = None self.chat_shared: Optional[ChatShared] = None self.story: Optional[Story] = None + self.external_reply: Optional[ExternalReplyInfo] = None + self.quote: Optional[TextQuote] = None + for key in options: setattr(self, key, options[key]) self.json = json_string @@ -8567,4 +8583,42 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: self.prize_description: Optional[str] = prize_description - \ No newline at end of file + +class TextQuote(JsonDeserializable): + """ + This object contains information about the quoted part of a message that is replied to by the given message. + + Telegram documentation: https://core.telegram.org/bots/api#textquote + + :param text: Text of the quoted part of a message that is replied to by the given message + :type text: :obj:`str` + + :param entities: Optional. Special entities that appear in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and custom_emoji entities are kept in quotes. + :type entities: :obj:`list` of :class:`MessageEntity` + + :param position: Approximate quote position in the original message in UTF-16 code units as specified by the sender + :type position: :obj:`int` + + :param is_manual: Optional. True, if the quote was chosen manually by the message sender. Otherwise, the quote was added automatically by the server. + :type is_manual: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`TextQuote` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + obj['entities'] = [MessageEntity.de_json(entity) for entity in obj.get('entities', [])] + + return cls(**obj) + + def __init__(self, text: str, entities: Optional[List[MessageEntity]] = None, + position: Optional[int] = None, is_manual: Optional[bool] = None) -> None: + self.text: str = text + self.entities: Optional[List[MessageEntity]] = entities + self.position: Optional[int] = position + self.is_manual: Optional[bool] = is_manual From 2604655ea434a844617398b03c66d244f08bd150 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 22:51:53 +0500 Subject: [PATCH 063/480] ReplyParameters support for sync, including backward compatibility --- telebot/__init__.py | 363 ++++++++++++++++++++++++++++++++++++------- telebot/apihelper.py | 201 +++++++++++------------- telebot/types.py | 80 ++++++++++ 3 files changed, 474 insertions(+), 170 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 23a95eea4..f8f60f987 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1530,7 +1530,8 @@ def send_message( allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send text messages. @@ -1577,6 +1578,9 @@ def send_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1586,11 +1590,21 @@ def send_message( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_message( - self.token, chat_id, text, disable_web_page_preview, reply_to_message_id, + self.token, chat_id, text, disable_web_page_preview, reply_markup, parse_mode, disable_notification, timeout, - entities, allow_sending_without_reply, protect_content=protect_content, message_thread_id=message_thread_id)) + entities, protect_content=protect_content, message_thread_id=message_thread_id)) def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -1648,7 +1662,8 @@ def copy_message( allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.MessageID: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID: """ Use this method to copy messages of any kind. @@ -1693,6 +1708,9 @@ def copy_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Additional parameters for replies to messages + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -1702,10 +1720,20 @@ def copy_message( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.MessageID.de_json( apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, - disable_notification, reply_to_message_id, allow_sending_without_reply, reply_markup, - timeout, protect_content, message_thread_id)) + disable_notification, reply_markup, + timeout, protect_content, message_thread_id, reply_parameters)) def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -1744,7 +1772,8 @@ def send_dice( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -1780,6 +1809,9 @@ def send_dice( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Additional parameters for replies to messages + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1787,10 +1819,20 @@ def send_dice( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_dice( - self.token, chat_id, emoji, disable_notification, reply_to_message_id, - reply_markup, timeout, allow_sending_without_reply, protect_content, message_thread_id) + self.token, chat_id, emoji, disable_notification, + reply_markup, timeout, protect_content, message_thread_id, reply_parameters) ) @@ -1862,11 +1904,21 @@ def send_photo( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_photo( - self.token, chat_id, photo, caption, reply_to_message_id, reply_markup, + self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - allow_sending_without_reply, protect_content, message_thread_id, has_spoiler)) + protect_content, message_thread_id, has_spoiler, reply_parameters)) # TODO: Rewrite this method like in API. def send_audio( @@ -1883,7 +1935,8 @@ def send_audio( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - thumb: Optional[Union[Any, str]]=None,) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[bool]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -1950,6 +2003,9 @@ def send_audio( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1958,15 +2014,25 @@ def send_audio( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if thumb is not None and thumbnail is None: thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') return types.Message.de_json( apihelper.send_audio( - self.token, chat_id, audio, caption, duration, performer, title, reply_to_message_id, + self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, allow_sending_without_reply, protect_content, message_thread_id)) + caption_entities, protect_content, message_thread_id, reply_parameters)) # TODO: Rewrite this method like in API. def send_voice( @@ -1980,7 +2046,8 @@ def send_voice( caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). @@ -2030,6 +2097,9 @@ def send_voice( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -2037,11 +2107,21 @@ def send_voice( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_voice( - self.token, chat_id, voice, caption, duration, reply_to_message_id, reply_markup, + self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - allow_sending_without_reply, protect_content, message_thread_id)) + protect_content, message_thread_id, reply_parameters)) # TODO: Rewrite this method like in API. def send_document( @@ -2059,7 +2139,8 @@ def send_document( disable_content_type_detection: Optional[bool]=None, data: Optional[Union[Any, str]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - thumb: Optional[Union[Any, str]]=None,) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send general files. @@ -2119,6 +2200,9 @@ def send_document( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2127,6 +2211,16 @@ def send_document( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if data and (not document): # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "document" instead.') @@ -2139,11 +2233,10 @@ def send_document( return types.Message.de_json( apihelper.send_data( self.token, chat_id, document, 'document', - reply_to_message_id = reply_to_message_id, reply_markup = reply_markup, parse_mode = parse_mode, + reply_parameters=reply_parameters, reply_markup = reply_markup, parse_mode = parse_mode, disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, - caption_entities = caption_entities, allow_sending_without_reply = allow_sending_without_reply, - disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, - protect_content = protect_content, message_thread_id = message_thread_id)) + caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, + visible_file_name = visible_file_name, protect_content = protect_content, message_thread_id = message_thread_id)) # TODO: Rewrite this method like in API. @@ -2158,7 +2251,8 @@ def send_sticker( protect_content:Optional[bool]=None, data: Union[Any, str]=None, message_thread_id: Optional[int]=None, - emoji: Optional[str]=None) -> types.Message: + emoji: Optional[str]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -2201,6 +2295,9 @@ def send_sticker( :param emoji: Emoji associated with the sticker; only for just uploaded stickers :type emoji: :obj:`str` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2213,13 +2310,22 @@ def send_sticker( logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_data( - self.token, chat_id, sticker, 'sticker', - reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, + self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, - allow_sending_without_reply=allow_sending_without_reply, - protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji)) + protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, + reply_parameters=reply_parameters)) def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -2240,7 +2346,8 @@ def send_video( data: Optional[Union[Any, str]]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, - thumb: Optional[Union[Any, str]]=None,) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2308,6 +2415,9 @@ def send_video( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + :param reply_parameters: Reply parameters + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2325,11 +2435,21 @@ def send_video( thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_video( - self.token, chat_id, video, duration, caption, reply_to_message_id, reply_markup, + self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, - caption_entities, allow_sending_without_reply, protect_content, message_thread_id, has_spoiler)) + caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters)) def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -2348,7 +2468,8 @@ def send_animation( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, - thumb: Optional[Union[Any, str]]=None,) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -2415,6 +2536,9 @@ def send_animation( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2423,14 +2547,24 @@ def send_animation( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if thumbnail is None and thumb is not None: thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') return types.Message.de_json( apihelper.send_animation( - self.token, chat_id, animation, duration, caption, reply_to_message_id, + self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, allow_sending_without_reply, protect_content, width, height, message_thread_id, has_spoiler)) + caption_entities, protect_content, width, height, message_thread_id, has_spoiler, reply_parameters)) # TODO: Rewrite this method like in API. def send_video_note( @@ -2445,7 +2579,8 @@ def send_video_note( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - thumb: Optional[Union[Any, str]]=None) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -2495,7 +2630,11 @@ def send_video_note( :type message_thread_id: :obj:`int` :param thumb: Deprecated. Use thumbnail instead - :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2507,10 +2646,20 @@ def send_video_note( thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_video_note( - self.token, chat_id, data, duration, length, reply_to_message_id, reply_markup, - disable_notification, timeout, thumbnail, allow_sending_without_reply, protect_content, message_thread_id)) + self.token, chat_id, data, duration, length, reply_markup, + disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters)) def send_media_group( @@ -2523,7 +2672,8 @@ def send_media_group( reply_to_message_id: Optional[int]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> List[types.Message]: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -2554,6 +2704,9 @@ def send_media_group( :param message_thread_id: Identifier of a message thread, in which the media group will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -2561,9 +2714,19 @@ def send_media_group( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + result = apihelper.send_media_group( - self.token, chat_id, media, disable_notification, reply_to_message_id, timeout, - allow_sending_without_reply, protect_content, message_thread_id) + self.token, chat_id, media, disable_notification, timeout, + protect_content, message_thread_id, reply_parameters) return [types.Message.de_json(msg) for msg in result] # TODO: Rewrite this method like in API. @@ -2580,7 +2743,8 @@ def send_location( proximity_alert_radius: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -2630,6 +2794,9 @@ def send_location( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2637,12 +2804,22 @@ def send_location( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_location( self.token, chat_id, latitude, longitude, live_period, - reply_to_message_id, reply_markup, disable_notification, timeout, + reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, - allow_sending_without_reply, protect_content, message_thread_id)) + protect_content, message_thread_id, reply_parameters)) def edit_message_live_location( self, latitude: float, longitude: float, @@ -2751,7 +2928,8 @@ def send_venue( google_place_id: Optional[str]=None, google_place_type: Optional[str]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -2809,6 +2987,9 @@ def send_venue( :param message_thread_id: The thread identifier of a message from which the reply will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2816,11 +2997,21 @@ def send_venue( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, - disable_notification, reply_to_message_id, reply_markup, timeout, - allow_sending_without_reply, google_place_id, google_place_type, protect_content, message_thread_id)) + disable_notification, reply_markup, timeout, + google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters)) # TODO: Rewrite this method like in API. @@ -2833,7 +3024,8 @@ def send_contact( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, - protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None) -> types.Message: + protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -2878,6 +3070,9 @@ def send_contact( :param message_thread_id: The thread identifier of a message from which the reply will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2885,11 +3080,21 @@ def send_contact( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( apihelper.send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, - disable_notification, reply_to_message_id, reply_markup, timeout, - allow_sending_without_reply, protect_content, message_thread_id)) + disable_notification, reply_markup, timeout, + protect_content, message_thread_id, reply_parameters)) def send_chat_action( self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None) -> bool: @@ -3956,7 +4161,8 @@ def send_game( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Used to send the game. @@ -3989,6 +4195,9 @@ def send_game( :param message_thread_id: The identifier of a message thread, in which the game message will be sent. :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters + :type reply_parameters: :obj:`ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -3996,10 +4205,20 @@ def send_game( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + result = apihelper.send_game( self.token, chat_id, game_short_name, disable_notification, - reply_to_message_id, reply_markup, timeout, - allow_sending_without_reply, protect_content, message_thread_id) + reply_markup, timeout, + protect_content, message_thread_id, reply_parameters) return types.Message.de_json(result) def set_game_score( @@ -4097,7 +4316,8 @@ def send_invoice( max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Sends invoice. @@ -4199,6 +4419,9 @@ def send_invoice( :param message_thread_id: The identifier of a message thread, in which the invoice message will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Required if the message is a reply. Additional interface options. + :type reply_parameters: :obj:`types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -4206,13 +4429,23 @@ def send_invoice( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + result = apihelper.send_invoice( self.token, chat_id, title, description, invoice_payload, provider_token, currency, prices, start_parameter, photo_url, photo_size, photo_width, photo_height, need_name, need_phone_number, need_email, need_shipping_address, send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification, - reply_to_message_id, reply_markup, provider_data, timeout, allow_sending_without_reply, - max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id) + reply_markup, provider_data, timeout, + max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters) return types.Message.de_json(result) def create_invoice_link(self, @@ -4337,7 +4570,8 @@ def send_poll( timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -4408,6 +4642,9 @@ def send_poll( :param message_thread_id: The identifier of a message thread, in which the poll will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: reply parameters. + :type reply_parameters: :obj:`ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -4417,6 +4654,16 @@ def send_poll( if isinstance(question, types.Poll): raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") + + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode @@ -4426,8 +4673,8 @@ def send_poll( question, options, is_anonymous, type, allows_multiple_answers, correct_option_id, explanation, explanation_parse_mode, open_period, close_date, is_closed, - disable_notification, reply_to_message_id, allow_sending_without_reply, - reply_markup, timeout, explanation_entities, protect_content, message_thread_id)) + disable_notification,reply_markup, timeout, explanation_entities, protect_content, message_thread_id, + reply_parameters)) def stop_poll( self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 8ae65814f..f41d92091 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -237,16 +237,14 @@ def download_file(token, file_path): def send_message( token, chat_id, text, - disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None, + disable_web_page_preview=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, - entities=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None): + entities=None, protect_content=None, + message_thread_id=None, reply_parameters=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if disable_web_page_preview is not None: payload['disable_web_page_preview'] = disable_web_page_preview - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -257,12 +255,13 @@ def send_message( payload['timeout'] = timeout if entities: payload['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, method='post') @@ -414,8 +413,8 @@ def forward_message( def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, - disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None, - reply_markup=None, timeout=None, protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, + reply_parameters=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -426,12 +425,9 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['caption_entities'] = _convert_entites(caption_entities) if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id - if reply_markup is not None: - payload['reply_markup'] = _convert_markup(reply_markup) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if timeout: payload['timeout'] = timeout if protect_content is not None: @@ -443,22 +439,21 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m def send_dice( token, chat_id, - emoji=None, disable_notification=None, reply_to_message_id=None, - reply_markup=None, timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + emoji=None, disable_notification=None, + reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: payload['emoji'] = emoji if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -468,10 +463,10 @@ def send_dice( def send_photo( token, chat_id, photo, - caption=None, reply_to_message_id=None, reply_markup=None, + caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, - caption_entities=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None, has_spoiler=None): + caption_entities=None, protect_content=None, + message_thread_id=None, has_spoiler=None,, reply_parameters=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -483,8 +478,6 @@ def send_photo( files = {'photo': photo} if caption: payload['caption'] = caption - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -495,32 +488,32 @@ def send_photo( payload['timeout'] = timeout if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id is not None: payload['message_thread_id'] = message_thread_id if has_spoiler is not None: payload['has_spoiler'] = has_spoiler + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') def send_media_group( token, chat_id, media, - disable_notification=None, reply_to_message_id=None, - timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + disable_notification=None, + timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendMediaGroup' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id is not None: @@ -533,11 +526,11 @@ def send_media_group( def send_location( token, chat_id, latitude, longitude, - live_period=None, reply_to_message_id=None, + live_period=None, reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, - proximity_alert_radius=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None): + proximity_alert_radius=None, protect_content=None, + message_thread_id=None, reply_parameters=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -548,10 +541,6 @@ def send_location( payload['heading'] = heading if proximity_alert_radius: payload['proximity_alert_radius'] = proximity_alert_radius - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if disable_notification is not None: @@ -562,6 +551,9 @@ def send_location( payload['protect_content'] = protect_content if message_thread_id is not None: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -611,9 +603,8 @@ def stop_message_live_location( def send_venue( token, chat_id, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, disable_notification=None, - reply_to_message_id=None, reply_markup=None, timeout=None, - allow_sending_without_reply=None, google_place_id=None, - google_place_type=None, protect_content=None, message_thread_id=None): + reply_markup=None, timeout=None, google_place_id=None, + google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -622,14 +613,10 @@ def send_venue( payload['foursquare_type'] = foursquare_type if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if google_place_id: payload['google_place_id'] = google_place_id if google_place_type: @@ -643,8 +630,8 @@ def send_venue( def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, - disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None, - allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, timeout=None, + protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -653,18 +640,17 @@ def send_contact( payload['vcard'] = vcard if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id is not None: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -679,10 +665,10 @@ def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=Non return _make_request(token, method_url, params=payload) -def send_video(token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None, +def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, - thumbnail=None, width=None, height=None, caption_entities=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None, has_spoiler=None): + thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, + message_thread_id=None, has_spoiler=None, reply_parameters=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -694,8 +680,6 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa payload['duration'] = duration if caption: payload['caption'] = caption - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -720,21 +704,22 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa payload['height'] = height if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id if has_spoiler is not None: payload['has_spoiler'] = has_spoiler + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') def send_animation( - token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None, + token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, - allow_sending_without_reply=None, protect_content=None, width=None, height=None, message_thread_id=None, + protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None has_spoiler=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} @@ -747,8 +732,6 @@ def send_animation( payload['duration'] = duration if caption: payload['caption'] = caption - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -767,8 +750,9 @@ def send_animation( payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if width: @@ -782,9 +766,9 @@ def send_animation( return _make_request(token, method_url, params=payload, files=files, method='post') -def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_message_id=None, reply_markup=None, +def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -796,8 +780,6 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_mess payload['caption'] = caption if duration: payload['duration'] = duration - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -808,18 +790,19 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_mess payload['timeout'] = timeout if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') -def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_message_id=None, reply_markup=None, - disable_notification=None, timeout=None, thumbnail=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None): +def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, + disable_notification=None, timeout=None, thumbnail=None, protect_content=None, + message_thread_id=None, reply_parameters=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -833,8 +816,6 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_m payload['length'] = length else: payload['length'] = 639 # seems like it is MAX length size - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if disable_notification is not None: @@ -849,8 +830,9 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_m files = {'thumbnail': thumbnail} else: payload['thumbnail'] = thumbnail - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -858,9 +840,9 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_m return _make_request(token, method_url, params=payload, files=files, method='post') -def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_to_message_id=None, +def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, - caption_entities=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -876,8 +858,6 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['performer'] = performer if title: payload['title'] = title - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -896,19 +876,21 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + return _make_request(token, method_url, params=payload, files=files, method='post') -def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None, +def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, - allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None, - protect_content = None, message_thread_id=None, emoji=None): + disable_content_type_detection=None, visible_file_name=None, + protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None): method_url = get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -919,8 +901,6 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m files = {data_type: file_data} else: payload[data_type] = data - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode and data_type == 'document': @@ -941,8 +921,9 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if method_url == 'sendDocument' and disable_content_type_detection is not None: @@ -1399,20 +1380,19 @@ def delete_message(token, chat_id, message_id, timeout=None): def send_game( token, chat_id, game_short_name, - disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None, - allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, timeout=None, + protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -1480,9 +1460,9 @@ def send_invoice( start_parameter = None, photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, - disable_notification=None, reply_to_message_id=None, reply_markup=None, provider_data=None, - timeout=None, allow_sending_without_reply=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, provider_data=None, + timeout=None, max_tip_amount=None, suggested_tip_amounts=None, + protect_content=None, message_thread_id=None, reply_parameters=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1548,16 +1528,12 @@ def send_invoice( payload['is_flexible'] = is_flexible if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if provider_data: payload['provider_data'] = provider_data if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if max_tip_amount is not None: payload['max_tip_amount'] = max_tip_amount if suggested_tip_amounts is not None: @@ -1566,6 +1542,9 @@ def send_invoice( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -1804,8 +1783,8 @@ def send_poll( question, options, is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, - disable_notification=False, reply_to_message_id=None, allow_sending_without_reply=None, - reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None): + disable_notification=False, + reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1836,10 +1815,8 @@ def send_poll( if disable_notification: payload['disable_notification'] = disable_notification - if reply_to_message_id is not None: - payload['reply_to_message_id'] = reply_to_message_id - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + payload['reply_parameters'] = reply_parameters.to_json() if reply_markup is not None: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: diff --git a/telebot/types.py b/telebot/types.py index bdb1d290d..4c53c3664 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8622,3 +8622,83 @@ def __init__(self, text: str, entities: Optional[List[MessageEntity]] = None, self.entities: Optional[List[MessageEntity]] = entities self.position: Optional[int] = position self.is_manual: Optional[bool] = is_manual + +class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable): + """ + Describes reply parameters for the message that is being sent. + + Telegram documentation: https://core.telegram.org/bots/api#replyparameters + + :param message_id: Identifier of the message that will be replied to in the current chat, or in the chat chat_id if it is specified + :type message_id: :obj:`int` + + :param chat_id: Optional. If the message to be replied to is from a different chat, unique identifier for the chat or username of the channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param allow_sending_without_reply: Optional. Pass True if the message should be sent even if the specified message to be replied to is not found; can be used only for replies in the same chat and forum topic. + :type allow_sending_without_reply: :obj:`bool` + + :param quote: Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing. The quote must be an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. The message will fail to send if the quote isn't found in the original message. + :type quote: :obj:`str` + + :param quote_parse_mode: Optional. Mode for parsing entities in the quote. See formatting options for more details. + :type quote_parse_mode: :obj:`str` + + :param quote_entities: Optional. A JSON-serialized list of special entities that appear in the quote. It can be specified instead of quote_parse_mode. + :type quote_entities: :obj:`list` of :class:`MessageEntity` + + :param quote_position: Optional. Position of the quote in the original message in UTF-16 code units + :type quote_position: :obj:`int` + + :return: Instance of the class + :rtype: :class:`ReplyParameters` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj.get('quote_entities', [])] + + return cls(**obj) + + + def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, + allow_sending_without_reply: Optional[bool] = None, quote: Optional[str] = None, + quote_parse_mode: Optional[str] = None, quote_entities: Optional[List[MessageEntity]] = None, + quote_position: Optional[int] = None) -> None: + self.message_id: int = message_id + self.chat_id: Optional[Union[int, str]] = chat_id + self.allow_sending_without_reply: Optional[bool] = allow_sending_without_reply + self.quote: Optional[str] = quote + self.quote_parse_mode: Optional[str] = quote_parse_mode + self.quote_entities: Optional[List[MessageEntity]] = quote_entities + self.quote_position: Optional[int] = quote_position + + + def to_dict(self) -> dict: + json_dict = { + 'message_id': self.message_id + } + + if self.chat_id is not None: + json_dict['chat_id'] = self.chat_id + if self.allow_sending_without_reply is not None: + json_dict['allow_sending_without_reply'] = self.allow_sending_without_reply + if self.quote is not None: + json_dict['quote'] = self.quote + if self.quote_parse_mode is not None: + json_dict['quote_parse_mode'] = self.quote_parse_mode + if self.quote_entities is not None: + json_dict['quote_entities'] = [entity.to_dict() for entity in self.quote_entities] + if self.quote_position is not None: + json_dict['quote_position'] = self.quote_position + + return json_dict + + def to_json(self) -> str: + return json.dumps(self.to_dict()) + + \ No newline at end of file From 6211366e186a3614e8888289abb360abf24ededb Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 22:53:22 +0500 Subject: [PATCH 064/480] Fix the typo and therefore tests --- telebot/apihelper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index f41d92091..6d9201098 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -466,7 +466,7 @@ def send_photo( caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None,, reply_parameters=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None From 3b5d2d789e847b1dcfe0e9950e14eb463ee55d19 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 22:55:19 +0500 Subject: [PATCH 065/480] Fix tests attempt 2 --- telebot/apihelper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 6d9201098..c44ac49e3 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -719,7 +719,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, - protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None + protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, has_spoiler=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} From c04ae539612e5bf8b6a54f0d0ec64b50bd65af30 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:18:39 +0500 Subject: [PATCH 066/480] Added reply_parameters to sync --- telebot/async_telebot.py | 363 ++++++++++++++++++++++++++++++++------ telebot/asyncio_helper.py | 188 ++++++++------------ 2 files changed, 384 insertions(+), 167 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 0f630ca5d..7546f2a84 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2514,7 +2514,8 @@ async def send_message( allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send text messages. @@ -2561,6 +2562,9 @@ async def send_message( :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2570,11 +2574,21 @@ async def send_message( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_message( - self.token, chat_id, text, disable_web_page_preview, reply_to_message_id, + self.token, chat_id, text, disable_web_page_preview, reply_markup, parse_mode, disable_notification, timeout, - entities, allow_sending_without_reply, protect_content, message_thread_id)) + entities, protect_content, message_thread_id, reply_parameters)) async def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -2631,7 +2645,8 @@ async def copy_message( allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.MessageID: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID: """ Use this method to copy messages of any kind. @@ -2677,6 +2692,9 @@ async def copy_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` """ @@ -2685,10 +2703,20 @@ async def copy_message( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.MessageID.de_json( await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, - disable_notification, reply_to_message_id, allow_sending_without_reply, reply_markup, - timeout, protect_content, message_thread_id)) + disable_notification, reply_markup, + timeout, protect_content, message_thread_id, reply_parameters)) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -2727,7 +2755,8 @@ async def send_dice( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -2762,6 +2791,9 @@ async def send_dice( :param message_thread_id: The identifier of a message thread, unique within the chat to which the message with the thread identifier belongs :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2770,10 +2802,20 @@ async def send_dice( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_dice( - self.token, chat_id, emoji, disable_notification, reply_to_message_id, - reply_markup, timeout, allow_sending_without_reply, protect_content, message_thread_id) + self.token, chat_id, emoji, disable_notification, + reply_markup, timeout, protect_content, message_thread_id, reply_parameters) ) async def send_photo( @@ -2787,7 +2829,8 @@ async def send_photo( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - has_spoiler: Optional[bool]=None) -> types.Message: + has_spoiler: Optional[bool]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2836,6 +2879,9 @@ async def send_photo( :param has_spoiler: Pass True, if the photo should be sent as a spoiler :type has_spoiler: :obj:`bool` + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2844,11 +2890,21 @@ async def send_photo( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_photo( - self.token, chat_id, photo, caption, reply_to_message_id, reply_markup, + self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - allow_sending_without_reply, protect_content, message_thread_id, has_spoiler)) + protect_content, message_thread_id, has_spoiler, reply_parameters)) async def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -2864,7 +2920,8 @@ async def send_audio( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - thumb: Optional[Union[Any, str]]=None) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -2930,6 +2987,9 @@ async def send_audio( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2943,11 +3003,21 @@ async def send_audio( thumbnail = thumb logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_audio( - self.token, chat_id, audio, caption, duration, performer, title, reply_to_message_id, + self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, allow_sending_without_reply, protect_content, message_thread_id)) + caption_entities, protect_content, message_thread_id, reply_parameters)) async def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], @@ -2960,7 +3030,8 @@ async def send_voice( caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). @@ -3009,6 +3080,9 @@ async def send_voice( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. """ @@ -3017,11 +3091,21 @@ async def send_voice( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_voice( - self.token, chat_id, voice, caption, duration, reply_to_message_id, reply_markup, + self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - allow_sending_without_reply, protect_content, message_thread_id)) + protect_content, message_thread_id, reply_parameters)) async def send_document( self, chat_id: Union[int, str], document: Union[Any, str], @@ -3039,7 +3123,8 @@ async def send_document( data: Optional[Union[Any, str]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - thumb: Optional[Union[Any, str]]=None) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send general files. @@ -3098,6 +3183,9 @@ async def send_document( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3116,14 +3204,24 @@ async def send_document( thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_data( self.token, chat_id, document, 'document', - reply_to_message_id = reply_to_message_id, reply_markup = reply_markup, parse_mode = parse_mode, + reply_markup = reply_markup, parse_mode = parse_mode, disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, - caption_entities = caption_entities, allow_sending_without_reply = allow_sending_without_reply, + caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content, - message_thread_id = message_thread_id)) + message_thread_id = message_thread_id, reply_parameters=reply_parameters)) async def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], @@ -3135,7 +3233,8 @@ async def send_sticker( protect_content: Optional[bool]=None, data: Union[Any, str]=None, message_thread_id: Optional[int]=None, - emoji: Optional[str]=None) -> types.Message: + emoji: Optional[str]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -3177,6 +3276,9 @@ async def send_sticker( :param emoji: Emoji associated with the sticker; only for just uploaded stickers :type emoji: :obj:`str` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3190,13 +3292,23 @@ async def send_sticker( logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_data( self.token, chat_id, sticker, 'sticker', - reply_to_message_id=reply_to_message_id, reply_markup=reply_markup, + reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, - allow_sending_without_reply=allow_sending_without_reply, protect_content=protect_content, - message_thread_id=message_thread_id, emoji=emoji)) + protect_content=protect_content, + message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters)) async def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -3217,7 +3329,8 @@ async def send_video( data: Optional[Union[Any, str]]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, - thumb: Optional[Union[Any, str]]=None) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -3284,6 +3397,9 @@ async def send_video( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3293,6 +3409,16 @@ async def send_video( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if data and not(video): # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "video" instead.') @@ -3304,9 +3430,9 @@ async def send_video( return types.Message.de_json( await asyncio_helper.send_video( - self.token, chat_id, video, duration, caption, reply_to_message_id, reply_markup, + self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, - caption_entities, allow_sending_without_reply, protect_content, message_thread_id, has_spoiler)) + caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -3325,7 +3451,8 @@ async def send_animation( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, - thumb: Optional[Union[Any, str]]=None) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -3391,6 +3518,9 @@ async def send_animation( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3400,15 +3530,25 @@ async def send_animation( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if thumb is not None and thumbnail is None: thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') return types.Message.de_json( await asyncio_helper.send_animation( - self.token, chat_id, animation, duration, caption, reply_to_message_id, + self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, allow_sending_without_reply, width, height, protect_content, message_thread_id, has_spoiler)) + caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -3422,7 +3562,8 @@ async def send_video_note( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - thumb: Optional[Union[Any, str]]=None) -> types.Message: + thumb: Optional[Union[Any, str]]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -3473,6 +3614,9 @@ async def send_video_note( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3481,14 +3625,24 @@ async def send_video_note( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if thumb is not None and thumbnail is None: thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') return types.Message.de_json( await asyncio_helper.send_video_note( - self.token, chat_id, data, duration, length, reply_to_message_id, reply_markup, - disable_notification, timeout, thumbnail, allow_sending_without_reply, protect_content, message_thread_id)) + self.token, chat_id, data, duration, length, reply_markup, + disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters)) async def send_media_group( self, chat_id: Union[int, str], @@ -3500,7 +3654,8 @@ async def send_media_group( reply_to_message_id: Optional[int]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> List[types.Message]: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -3530,6 +3685,9 @@ async def send_media_group( :param message_thread_id: Identifier of a message thread, in which the messages will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] @@ -3538,9 +3696,18 @@ async def send_media_group( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + result = await asyncio_helper.send_media_group( - self.token, chat_id, media, disable_notification, reply_to_message_id, timeout, - allow_sending_without_reply, protect_content, message_thread_id) + self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters) return [types.Message.de_json(msg) for msg in result] async def send_location( @@ -3556,7 +3723,8 @@ async def send_location( proximity_alert_radius: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -3605,6 +3773,9 @@ async def send_location( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3613,12 +3784,22 @@ async def send_location( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_location( self.token, chat_id, latitude, longitude, live_period, - reply_to_message_id, reply_markup, disable_notification, timeout, + reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, - allow_sending_without_reply, protect_content, message_thread_id)) + protect_content, message_thread_id, reply_parameters)) async def edit_message_live_location( self, latitude: float, longitude: float, @@ -3726,7 +3907,8 @@ async def send_venue( google_place_id: Optional[str]=None, google_place_type: Optional[str]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -3783,6 +3965,9 @@ async def send_venue( :param message_thread_id: The thread to which the message will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3791,11 +3976,21 @@ async def send_venue( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, - disable_notification, reply_to_message_id, reply_markup, timeout, - allow_sending_without_reply, google_place_id, google_place_type, protect_content, message_thread_id) + disable_notification, reply_markup, timeout, + google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters) ) async def send_contact( @@ -3808,7 +4003,8 @@ async def send_contact( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -3852,6 +4048,9 @@ async def send_contact( :param message_thread_id: The thread to which the message will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3860,11 +4059,21 @@ async def send_contact( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + return types.Message.de_json( await asyncio_helper.send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, - disable_notification, reply_to_message_id, reply_markup, timeout, - allow_sending_without_reply, protect_content, message_thread_id) + disable_notification, reply_markup, timeout, + protect_content, message_thread_id, reply_parameters) ) async def send_chat_action( @@ -4931,7 +5140,8 @@ async def send_game( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Used to send the game. @@ -4963,6 +5173,9 @@ async def send_game( :param message_thread_id: Identifier of the thread to which the message will be sent. :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` @@ -4971,10 +5184,20 @@ async def send_game( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + result = await asyncio_helper.send_game( self.token, chat_id, game_short_name, disable_notification, - reply_to_message_id, reply_markup, timeout, - allow_sending_without_reply, protect_content, message_thread_id) + reply_markup, timeout, + protect_content, message_thread_id, reply_parameters) return types.Message.de_json(result) async def set_game_score( @@ -5071,7 +5294,8 @@ async def send_invoice( max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Sends invoice. @@ -5172,6 +5396,9 @@ async def send_invoice( :param message_thread_id: The identifier of a message thread, in which the invoice message will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` @@ -5180,13 +5407,23 @@ async def send_invoice( protect_content = self.protect_content if (protect_content is None) else protect_content allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + result = await asyncio_helper.send_invoice( self.token, chat_id, title, description, invoice_payload, provider_token, currency, prices, start_parameter, photo_url, photo_size, photo_width, photo_height, need_name, need_phone_number, need_email, need_shipping_address, send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification, - reply_to_message_id, reply_markup, provider_data, timeout, allow_sending_without_reply, - max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id) + reply_markup, provider_data, timeout, + max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters) return types.Message.de_json(result) @@ -5311,7 +5548,8 @@ async def send_poll( timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -5381,6 +5619,9 @@ async def send_poll( :param message_thread_id: The identifier of a message thread, in which the poll will be sent :type message_thread_id: :obj:`int` + + :param reply_parameters: Reply parameters. + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` @@ -5390,6 +5631,16 @@ async def send_poll( allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode + if allow_sending_without_reply or reply_to_message_id: + # show a deprecation warning + logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + allow_sending_without_reply=allow_sending_without_reply, + message_id=reply_to_message_id + ) + if isinstance(question, types.Poll): raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") @@ -5399,8 +5650,8 @@ async def send_poll( question, options, is_anonymous, type, allows_multiple_answers, correct_option_id, explanation, explanation_parse_mode, open_period, close_date, is_closed, - disable_notification, reply_to_message_id, allow_sending_without_reply, - reply_markup, timeout, explanation_entities, protect_content, message_thread_id)) + disable_notification, + reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters)) async def stop_poll( self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 91538abc4..3cfd3fed8 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -278,16 +278,14 @@ async def _check_result(method_name, result: aiohttp.ClientResponse): async def send_message( token, chat_id, text, - disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None, + disable_web_page_preview=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, - entities=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None): + entities=None, protect_content=None, + message_thread_id=None, reply_parameters=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} if disable_web_page_preview is not None: params['disable_web_page_preview'] = disable_web_page_preview - if reply_to_message_id: - params['reply_to_message_id'] = reply_to_message_id if reply_markup: params['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -298,8 +296,8 @@ async def send_message( params['timeout'] = timeout if entities: params['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities)) - if allow_sending_without_reply is not None: - params['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + params['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: params['protect_content'] = protect_content if message_thread_id: @@ -406,8 +404,8 @@ async def forward_message( async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, - disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None, - reply_markup=None, timeout=None, protect_content=None, message_thread_id=None): + disable_notification=None, + reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -418,12 +416,10 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['caption_entities'] = await _convert_entites(caption_entities) if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup is not None: payload['reply_markup'] = await _convert_markup(reply_markup) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if timeout: payload['timeout'] = timeout if protect_content is not None: @@ -435,36 +431,34 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p async def send_dice( token, chat_id, - emoji=None, disable_notification=None, reply_to_message_id=None, - reply_markup=None, timeout=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None): + emoji=None, disable_notification=None, + reply_markup=None, timeout=None, protect_content=None, + message_thread_id=None,reply_parameters=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: payload['emoji'] = emoji if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return await _process_request(token, method_url, params=payload) async def send_photo( token, chat_id, photo, - caption=None, reply_to_message_id=None, reply_markup=None, + caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, - caption_entities=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None, has_spoiler=None): + caption_entities=None, protect_content=None, + message_thread_id=None, has_spoiler=None,reply_parameters=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -476,8 +470,6 @@ async def send_photo( files = {'photo': photo} if caption: payload['caption'] = caption - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -488,8 +480,8 @@ async def send_photo( payload['timeout'] = timeout if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -501,23 +493,21 @@ async def send_photo( async def send_media_group( token, chat_id, media, - disable_notification=None, reply_to_message_id=None, - timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + disable_notification=None, + timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendMediaGroup' media_json, files = await convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return await _process_request( token, method_url, params=payload, method='post' if files else 'get', @@ -526,10 +516,10 @@ async def send_media_group( async def send_location( token, chat_id, latitude, longitude, - live_period=None, reply_to_message_id=None, + live_period=None, reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, - proximity_alert_radius=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -540,10 +530,8 @@ async def send_location( payload['heading'] = heading if proximity_alert_radius: payload['proximity_alert_radius'] = proximity_alert_radius - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if disable_notification is not None: @@ -603,9 +591,9 @@ async def stop_message_live_location( async def send_venue( token, chat_id, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, disable_notification=None, - reply_to_message_id=None, reply_markup=None, timeout=None, - allow_sending_without_reply=None, google_place_id=None, - google_place_type=None, protect_content=None, message_thread_id=None): + reply_markup=None, timeout=None, + google_place_id=None, + google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -614,14 +602,12 @@ async def send_venue( payload['foursquare_type'] = foursquare_type if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if google_place_id: payload['google_place_id'] = google_place_id if google_place_type: @@ -635,8 +621,8 @@ async def send_venue( async def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, - disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None, - allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, timeout=None, + protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -645,14 +631,12 @@ async def send_contact( payload['vcard'] = vcard if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -670,10 +654,10 @@ async def send_chat_action(token, chat_id, action, timeout=None, message_thread_ return await _process_request(token, method_url, params=payload) -async def send_video(token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None, +async def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, - thumbnail=None, width=None, height=None, caption_entities=None, allow_sending_without_reply=None, - protect_content=None, message_thread_id=None, has_spoiler=None): + thumbnail=None, width=None, height=None, caption_entities=None, + protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -685,8 +669,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_to payload['duration'] = duration if caption: payload['caption'] = caption - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -711,8 +695,6 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_to payload['height'] = height if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -723,10 +705,10 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_to async def send_animation( - token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None, + token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, - allow_sending_without_reply=None, width=None, height=None, protect_content=None, message_thread_id=None, - has_spoiler=None): + width=None, height=None, protect_content=None, message_thread_id=None, + has_spoiler=None,reply_parameters=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -738,8 +720,8 @@ async def send_animation( payload['duration'] = duration if caption: payload['caption'] = caption - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -758,8 +740,6 @@ async def send_animation( payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if width: payload['width'] = width if height: @@ -773,9 +753,9 @@ async def send_animation( return await _process_request(token, method_url, params=payload, files=files, method='post') -async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_message_id=None, reply_markup=None, +async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -787,8 +767,8 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_t payload['caption'] = caption if duration: payload['duration'] = duration - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -799,8 +779,6 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_t payload['timeout'] = timeout if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -808,9 +786,9 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_t return await _process_request(token, method_url, params=payload, files=files, method='post') -async def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_message_id=None, reply_markup=None, - disable_notification=None, timeout=None, thumbnail=None, allow_sending_without_reply=None, protect_content=None, - message_thread_id=None): +async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, + disable_notification=None, timeout=None, thumbnail=None, protect_content=None, + message_thread_id=None,reply_parameters=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -824,8 +802,8 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, repl payload['length'] = length else: payload['length'] = 639 # seems like it is MAX length size - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if disable_notification is not None: @@ -840,8 +818,6 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, repl files = {'thumbnail': thumbnail} else: payload['thumbnail'] = thumbnail - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -849,9 +825,9 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, repl return await _process_request(token, method_url, params=payload, files=files, method='post') -async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_to_message_id=None, +async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, - caption_entities=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -867,8 +843,8 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['performer'] = performer if title: payload['title'] = title - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -887,8 +863,6 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -896,10 +870,10 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform return await _process_request(token, method_url, params=payload, files=files, method='post') -async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None, +async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, - allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None, - message_thread_id=None, emoji=None): + disable_content_type_detection=None, visible_file_name=None, protect_content=None, + message_thread_id=None, emoji=None,reply_parameters=None): method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -910,8 +884,8 @@ async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, r files = {data_type: file_data} else: payload[data_type] = data - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if parse_mode and data_type == 'document': @@ -932,8 +906,6 @@ async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, r payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if method_url == 'sendDocument' and disable_content_type_detection is not None: @@ -1386,20 +1358,18 @@ async def delete_message(token, chat_id, message_id, timeout=None): async def send_game( token, chat_id, game_short_name, - disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None, - allow_sending_without_reply=None, protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, timeout=None, + protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -1467,9 +1437,9 @@ async def send_invoice( start_parameter = None, photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, - disable_notification=None, reply_to_message_id=None, reply_markup=None, provider_data=None, - timeout=None, allow_sending_without_reply=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None): + disable_notification=None, reply_markup=None, provider_data=None, + timeout=None, max_tip_amount=None, suggested_tip_amounts=None, + protect_content=None, message_thread_id=None,reply_parameters=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1535,16 +1505,14 @@ async def send_invoice( payload['is_flexible'] = is_flexible if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_to_message_id: - payload['reply_to_message_id'] = reply_to_message_id + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if provider_data: payload['provider_data'] = provider_data if timeout: payload['timeout'] = timeout - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply if max_tip_amount is not None: payload['max_tip_amount'] = max_tip_amount if suggested_tip_amounts is not None: @@ -1788,8 +1756,8 @@ async def send_poll( question, options, is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, - disable_notification=False, reply_to_message_id=None, allow_sending_without_reply=None, - reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None): + disable_notification=False, + reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1820,10 +1788,8 @@ async def send_poll( if disable_notification: payload['disable_notification'] = disable_notification - if reply_to_message_id is not None: - payload['reply_to_message_id'] = reply_to_message_id - if allow_sending_without_reply is not None: - payload['allow_sending_without_reply'] = allow_sending_without_reply + if reply_parameters is not None: + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup is not None: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: From 545cedb8e20662650f0f1ba9be4b725f375af3f8 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:24:33 +0500 Subject: [PATCH 067/480] Fix some issues with the previous commit --- telebot/__init__.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index f8f60f987..3b1f9c91d 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1604,7 +1604,7 @@ def send_message( apihelper.send_message( self.token, chat_id, text, disable_web_page_preview, reply_markup, parse_mode, disable_notification, timeout, - entities, protect_content=protect_content, message_thread_id=message_thread_id)) + entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters)) def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -1847,7 +1847,8 @@ def send_photo( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - has_spoiler: Optional[bool]=None) -> types.Message: + has_spoiler: Optional[bool]=None, + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -1895,6 +1896,9 @@ def send_photo( :param has_spoiler: Pass True, if the photo should be sent as a spoiler :type has_spoiler: :obj:`bool` + + :param reply_parameters: Additional parameters for replies to messages + :type reply_parameters: :class:`telebot.types.ReplyParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -1936,7 +1940,7 @@ def send_audio( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[bool]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, From b8ef19d67e3541e0a755907551067ab38a45f9bd Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:33:19 +0500 Subject: [PATCH 068/480] Added support for linkpreviewoptions --- telebot/__init__.py | 37 ++++++++++++++++++++++++++++++++----- telebot/apihelper.py | 14 +++++++------- telebot/async_telebot.py | 35 ++++++++++++++++++++++++++++++----- telebot/asyncio_helper.py | 14 +++++++------- telebot/types.py | 21 +++++++++++++++++++-- 5 files changed, 95 insertions(+), 26 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 3b1f9c91d..4e223581f 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1531,7 +1531,8 @@ def send_message( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + link_preview_options : Optional[types.ReplyParameters]=None) -> types.Message: """ Use this method to send text messages. @@ -1581,6 +1582,9 @@ def send_message( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param link_preview_options: Link preview options. + :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1600,11 +1604,20 @@ def send_message( message_id=reply_to_message_id ) + if disable_web_page_preview: + # show a deprecation warning + logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + disable_web_page_preview=disable_web_page_preview + ) + return types.Message.de_json( apihelper.send_message( - self.token, chat_id, text, disable_web_page_preview, + self.token, chat_id, text, reply_markup, parse_mode, disable_notification, timeout, - entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters)) + entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, link_preview_options=link_preview_options)) def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -4050,7 +4063,8 @@ def edit_message_text( parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + link_preview_options : Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]: """ Use this method to edit text and game messages. @@ -4080,14 +4094,27 @@ def edit_message_text( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`InlineKeyboardMarkup` + :param link_preview_options: A JSON-serialized object for options used to automatically generate previews for links. + :type link_preview_options: :obj:`LinkPreviewOptions` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview + if disable_web_page_preview: + # show a deprecation warning + logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + disable_web_page_preview=disable_web_page_preview + ) + + result = apihelper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, - entities, disable_web_page_preview, reply_markup) + entities, reply_markup, link_preview_options) if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index c44ac49e3..869f5b52c 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -237,14 +237,14 @@ def download_file(token, file_path): def send_message( token, chat_id, text, - disable_web_page_preview=None, reply_markup=None, + reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, - message_thread_id=None, reply_parameters=None): + message_thread_id=None, reply_parameters=None, link_preview_options=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} - if disable_web_page_preview is not None: - payload['disable_web_page_preview'] = disable_web_page_preview + if link_preview_options is not None: + payload['link_preview'] = link_preview_options.to_json() if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -1300,7 +1300,7 @@ def unpin_all_chat_messages(token, chat_id): # Updating messages def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, - entities = None, disable_web_page_preview=None, reply_markup=None): + entities = None, reply_markup=None, link_preview_options=None): method_url = r'editMessageText' payload = {'text': text} if chat_id: @@ -1313,10 +1313,10 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message payload['parse_mode'] = parse_mode if entities: payload['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities)) - if disable_web_page_preview is not None: - payload['disable_web_page_preview'] = disable_web_page_preview if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if link_preview_options is not None: + payload['link_preview'] = link_preview_options.to_json() return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 7546f2a84..955dcfd33 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2515,7 +2515,8 @@ async def send_message( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + link_preview_options: Optional[types.LinkPreviewOptions]=None) -> types.Message: """ Use this method to send text messages. @@ -2565,6 +2566,9 @@ async def send_message( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param link_preview_options: Options for previewing links. + :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2583,12 +2587,20 @@ async def send_message( allow_sending_without_reply=allow_sending_without_reply, message_id=reply_to_message_id ) + if disable_web_page_preview: + # show a deprecation warning + logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + disable_web_page_preview=disable_web_page_preview + ) return types.Message.de_json( await asyncio_helper.send_message( - self.token, chat_id, text, disable_web_page_preview, + self.token, chat_id, text, reply_markup, parse_mode, disable_notification, timeout, - entities, protect_content, message_thread_id, reply_parameters)) + entities, protect_content, message_thread_id, reply_parameters, link_preview_options)) async def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -5025,7 +5037,8 @@ async def edit_message_text( parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + link_preview_options: Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]: """ Use this method to edit text and game messages. @@ -5055,14 +5068,26 @@ async def edit_message_text( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`InlineKeyboardMarkup` + :param link_preview_options: A JSON-serialized object for options used to automatically generate Telegram link previews for messages. + :type link_preview_options: :obj:`LinkPreviewOptions` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview + if disable_web_page_preview: + # show a deprecation warning + logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + disable_web_page_preview=disable_web_page_preview + ) + result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, - entities, disable_web_page_preview, reply_markup) + entities, reply_markup, link_preview_options) if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 3cfd3fed8..2aeebff32 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -278,14 +278,14 @@ async def _check_result(method_name, result: aiohttp.ClientResponse): async def send_message( token, chat_id, text, - disable_web_page_preview=None, reply_markup=None, + reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, - message_thread_id=None, reply_parameters=None): + message_thread_id=None, reply_parameters=None, link_preview_options=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} - if disable_web_page_preview is not None: - params['disable_web_page_preview'] = disable_web_page_preview + if link_preview_options is not None: + params['link_preview_options'] = json.dumps(link_preview_options.to_dict()) if reply_markup: params['reply_markup'] = await _convert_markup(reply_markup) if parse_mode: @@ -1278,7 +1278,7 @@ async def unpin_all_chat_messages(token, chat_id): # Updating messages async def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, - entities = None, disable_web_page_preview=None, reply_markup=None): + entities = None, reply_markup=None, link_preview_options=None): method_url = r'editMessageText' payload = {'text': text} if chat_id: @@ -1291,10 +1291,10 @@ async def edit_message_text(token, text, chat_id=None, message_id=None, inline_m payload['parse_mode'] = parse_mode if entities: payload['entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(entities)) - if disable_web_page_preview is not None: - payload['disable_web_page_preview'] = disable_web_page_preview if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) + if link_preview_options is not None: + payload['link_preview_options'] = link_preview_options.to_json() return await _process_request(token, method_url, params=payload, method='post') diff --git a/telebot/types.py b/telebot/types.py index 4c53c3664..31365b01d 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8409,7 +8409,7 @@ def __init__(self, date: int, chat: Optional[Chat] = None, message_id: Optional[ self.author_signature: Optional[str] = author_signature -class LinkPreviewOptions(JsonDeserializable): +class LinkPreviewOptions(JsonDeserializable, Dictionaryable, JsonSerializable): """ Describes the options used for link preview generation. @@ -8453,6 +8453,24 @@ def __init__(self, is_disabled: Optional[bool] = None, url: Optional[str] = None self.prefer_large_media: Optional[bool] = prefer_large_media self.show_above_text: Optional[bool] = show_above_text + def to_dict(self) -> dict: + json_dict = {} + + if self.is_disabled is not None: + json_dict['is_disabled'] = self.is_disabled + if self.url is not None: + json_dict['url'] = self.url + if self.prefer_small_media is not None: + json_dict['prefer_small_media'] = self.prefer_small_media + if self.prefer_large_media is not None: + json_dict['prefer_large_media'] = self.prefer_large_media + if self.show_above_text is not None: + json_dict['show_above_text'] = self.show_above_text + + + def to_json(self) -> str: + return json.dumps(self.to_dict()) + class Giveaway(JsonDeserializable): """ @@ -8701,4 +8719,3 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) - \ No newline at end of file From 0485c31ef4202f2828c037ddb448eb6a92696436 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:37:39 +0500 Subject: [PATCH 069/480] Replaced the field disable_web_page_preview with link_preview_options in the class InputTextMessageContent. --- telebot/types.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 31365b01d..c76b8d049 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3628,11 +3628,16 @@ class InputTextMessageContent(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.InputTextMessageContent` """ - def __init__(self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None): + def __init__(self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None, link_preview_options=None): self.message_text: str = message_text self.parse_mode: str = parse_mode self.entities: List[MessageEntity] = entities - self.disable_web_page_preview: bool = disable_web_page_preview + link_preview_options: LinkPreviewOptions = link_preview_options + if disable_web_page_preview is not None and link_preview_options is None: + # deprecated + self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(disable_web_page_preview) + + def to_dict(self): json_dict = {'message_text': self.message_text} @@ -3640,8 +3645,8 @@ def to_dict(self): json_dict['parse_mode'] = self.parse_mode if self.entities: json_dict['entities'] = MessageEntity.to_list_of_dicts(self.entities) - if self.disable_web_page_preview is not None: - json_dict['disable_web_page_preview'] = self.disable_web_page_preview + if self.link_preview_options: + json_dict['link_preview_options'] = self.link_preview_options.to_dict() return json_dict From a26117416b3cd8a40ae92c7ad8fbfd5e4dde781e Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:39:35 +0500 Subject: [PATCH 070/480] Added the field link_preview_options to the class Message with information about the link preview options used to send the message. --- telebot/types.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index c76b8d049..26cd50dca 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -836,6 +836,10 @@ class Message(JsonDeserializable): appear in the text :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :param link_preview_options: Optional. Options used for link preview generation for the message, + if it is a text message and link preview options were changed + :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param animation: Optional. Message is an animation, information about the animation. For backward compatibility, when this field is set, the document field will also be set :type animation: :class:`telebot.types.Animation` @@ -1221,6 +1225,10 @@ def de_json(cls, json_string): opts['quote'] = TextQuote.de_json(obj['quote']) content_type = 'text' # Here too, check the content types + if 'link_preview_options' in obj: + opts['link_preview_options'] = LinkPreviewOptions.de_json(obj['link_preview_options']) + + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod @@ -1321,6 +1329,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.story: Optional[Story] = None self.external_reply: Optional[ExternalReplyInfo] = None self.quote: Optional[TextQuote] = None + self.LinkPreviewOptions: Optional[LinkPreviewOptions] = None for key in options: setattr(self, key, options[key]) From c406e6c972a9afbb2fcc1676687a44a8ad1bfa20 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:52:14 +0500 Subject: [PATCH 071/480] Added Copy,Delete,Forward Messages to sync and async --- telebot/__init__.py | 91 +++++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 46 ++++++++++++++++++++ telebot/async_telebot.py | 90 ++++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 49 +++++++++++++++++++++ 4 files changed, 276 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4e223581f..daad4a88a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1776,6 +1776,97 @@ def delete_message(self, chat_id: Union[int, str], message_id: int, :rtype: :obj:`bool` """ return apihelper.delete_message(self.token, chat_id, message_id, timeout) + + def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): + """ + Use this method to delete multiple messages in a chat. + The number of messages to be deleted must not exceed 100. + If the chat is a private chat, the user must be an administrator of the chat for this to work and must have the appropriate admin rights. + Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#deletemessages + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param message_ids: Identifiers of the messages to be deleted + :type message_ids: :obj:`list` of :obj:`int` + + :return: Returns True on success. + + """ + return apihelper.delete_messages(self.token, chat_id, message_ids) + + def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, + message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: + """ + Use this method to forward messages of any kind. + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + :type from_chat_id: :obj:`int` or :obj:`str` + + :param message_ids: Message identifiers in the chat specified in from_chat_id + :type message_ids: :obj:`list` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound + :type disable_notification: :obj:`bool` + + :param message_thread_id: Identifier of a message thread, in which the messages will be sent + :type message_thread_id: :obj:`int` + + :param protect_content: Protects the contents of the forwarded message from forwarding and saving + :type protect_content: :obj:`bool` + + :return: On success, the sent Message is returned. + :rtype: :class:`telebot.types.MessageID` + """ + + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification + protect_content = self.protect_content if (protect_content is None) else protect_content + + return types.MessageID.de_json( + apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id)) + + def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], + disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, + protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: + """ + Use this method to copy messages of any kind. + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + :type from_chat_id: :obj:`int` or :obj:`str` + + :param message_ids: Message identifiers in the chat specified in from_chat_id + :type message_ids: :obj:`list` of :obj:`int` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound + :type disable_notification: :obj:`bool` + + :param message_thread_id: Identifier of a message thread, in which the messages will be sent + :type message_thread_id: :obj:`int` + + :param protect_content: Protects the contents of the forwarded message from forwarding and saving + :type protect_content: :obj:`bool` + + :param remove_caption: Pass True to copy the messages without their captions + :type remove_caption: :obj:`bool` + + :return: On success, an array of MessageId of the sent messages is returned. + :rtype: :obj:`list` of :class:`telebot.types.MessageID` + """ + disable_notification = self.disable_notification if disable_notification is None else disable_notification + protect_content = self.protect_content if protect_content is None else protect_content + + return [types.MessageID.de_json(message_id) for message_id in + apihelper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, + protect_content, message_thread_id, remove_caption)] + def send_dice( self, chat_id: Union[int, str], diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 869f5b52c..88a4e697a 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1904,6 +1904,52 @@ def unhide_general_forum_topic(token, chat_id): payload = {'chat_id': chat_id} return _make_request(token, method_url, params=payload) +def delete_messages(token, chat_id, message_ids): + method_url = 'deleteMessages' + payload = { + 'chat_id': chat_id, + 'message_ids': message_ids + } + return _make_request(token, method_url, params=payload) + +def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, + message_thread_id=None, protect_content=None): + method_url = 'forwardMessages' + payload = { + 'chat_id': chat_id, + 'from_chat_id': from_chat_id, + 'message_ids': message_ids, + } + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if message_thread_id is not None: + payload['message_thread_id'] = message_thread_id + if protect_content is not None: + payload['protect_content'] = protect_content + + result = _make_request(token, method_url, params=payload) + return result + +def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, + message_thread_id=None, protect_content=None, remove_caption=None): + method_url = 'copyMessages' + payload = { + 'chat_id': chat_id, + 'from_chat_id': from_chat_id, + 'message_ids': message_ids, + } + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if message_thread_id is not None: + payload['message_thread_id'] = message_thread_id + if protect_content is not None: + payload['protect_content'] = protect_content + if remove_caption is not None: + payload['remove_caption'] = remove_caption + + result = _make_request(token, method_url, params=payload) + return result + def _convert_list_json_serializable(results): ret = '' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 955dcfd33..4adc7b424 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2758,6 +2758,96 @@ async def delete_message(self, chat_id: Union[int, str], message_id: int, :rtype: :obj:`bool` """ return await asyncio_helper.delete_message(self.token, chat_id, message_id, timeout) + + async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): + """ + Use this method to delete multiple messages in a chat. + The number of messages to be deleted must not exceed 100. + If the chat is a private chat, the user must be an administrator of the chat for this to work and must have the appropriate admin rights. + Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#deletemessages + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param message_ids: Identifiers of the messages to be deleted + :type message_ids: :obj:`list` of :obj:`int` + + :return: Returns True on success. + + """ + return await asyncio_helper.delete_messages(self.token, chat_id, message_ids) + + async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, + message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: + """ + Use this method to forward messages of any kind. + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + :type from_chat_id: :obj:`int` or :obj:`str` + + :param message_ids: Message identifiers in the chat specified in from_chat_id + :type message_ids: :obj:`list` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound + :type disable_notification: :obj:`bool` + + :param message_thread_id: Identifier of a message thread, in which the messages will be sent + :type message_thread_id: :obj:`int` + + :param protect_content: Protects the contents of the forwarded message from forwarding and saving + :type protect_content: :obj:`bool` + + :return: On success, the sent Message is returned. + :rtype: :class:`telebot.types.MessageID` + """ + + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification + protect_content = self.protect_content if (protect_content is None) else protect_content + result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id) + return types.MessageID.de_json( + result) + + async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], + disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, + protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: + """ + Use this method to copy messages of any kind. + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + :type from_chat_id: :obj:`int` or :obj:`str` + + :param message_ids: Message identifiers in the chat specified in from_chat_id + :type message_ids: :obj:`list` of :obj:`int` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound + :type disable_notification: :obj:`bool` + + :param message_thread_id: Identifier of a message thread, in which the messages will be sent + :type message_thread_id: :obj:`int` + + :param protect_content: Protects the contents of the forwarded message from forwarding and saving + :type protect_content: :obj:`bool` + + :param remove_caption: Pass True to copy the messages without their captions + :type remove_caption: :obj:`bool` + + :return: On success, an array of MessageId of the sent messages is returned. + :rtype: :obj:`list` of :class:`telebot.types.MessageID` + """ + disable_notification = self.disable_notification if disable_notification is None else disable_notification + protect_content = self.protect_content if protect_content is None else protect_content + result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, + protect_content, message_thread_id, remove_caption) + return [types.MessageID.de_json(message_id) for message_id in + result] async def send_dice( self, chat_id: Union[int, str], diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 2aeebff32..ae119078e 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1871,6 +1871,53 @@ async def unhide_general_forum_topic(token, chat_id): payload = {'chat_id': chat_id} return await _process_request(token, method_url, params=payload) +async def delete_messages(token, chat_id, message_ids): + method_url = 'deleteMessages' + payload = { + 'chat_id': chat_id, + 'message_ids': message_ids + } + return await _process_request(token, method_url, params=payload) + +async def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, + message_thread_id=None, protect_content=None): + method_url = 'forwardMessages' + payload = { + 'chat_id': chat_id, + 'from_chat_id': from_chat_id, + 'message_ids': message_ids, + } + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if message_thread_id is not None: + payload['message_thread_id'] = message_thread_id + if protect_content is not None: + payload['protect_content'] = protect_content + + result = await _process_request(token, method_url, params=payload) + return result + +async def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, + message_thread_id=None, protect_content=None, remove_caption=None): + method_url = 'copyMessages' + payload = { + 'chat_id': chat_id, + 'from_chat_id': from_chat_id, + 'message_ids': message_ids, + } + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if message_thread_id is not None: + payload['message_thread_id'] = message_thread_id + if protect_content is not None: + payload['protect_content'] = protect_content + if remove_caption is not None: + payload['remove_caption'] = remove_caption + + result = await _process_request(token, method_url, params=payload) + return result + + async def _convert_list_json_serializable(results): ret = '' for r in results: @@ -1999,3 +2046,5 @@ class RequestTimeout(Exception): This class represents a request timeout. """ pass + + From 254387d9850c1bbf51b84b9c65f6f5058662bc86 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 29 Dec 2023 23:58:52 +0500 Subject: [PATCH 072/480] Renamed the class KeyboardButtonRequestUser to KeyboardButtonRequestUsers and added the field max_quantity to it. Renamed the field request_user in the class KeyboardButton to request_users. The old name will still work for backward compatibility. --- telebot/types.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 26cd50dca..13a4333b8 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2337,13 +2337,12 @@ def to_dict(self): return {'type': self.type} - -class KeyboardButtonRequestUser(Dictionaryable): +class KeyboardButtonRequestUsers(Dictionaryable): """ This object defines the criteria used to request a suitable user. The identifier of the selected user will be shared with the bot when the corresponding button is pressed. - Telegram documentation: https://core.telegram.org/bots/api#keyboardbuttonrequestuser + Telegram documentation: https://core.telegram.org/bots/api#keyboardbuttonrequestusers :param request_id: Signed 32-bit identifier of the request, which will be received back in the UserShared object. Must be unique within the message @@ -2357,15 +2356,19 @@ class KeyboardButtonRequestUser(Dictionaryable): If not specified, no additional restrictions are applied. :type user_is_premium: :obj:`bool` + :param max_quantity: Optional. The maximum number of users to be selected; 1-10. Defaults to 1. + :type max_quantity: :obj:`int` + :return: Instance of the class - :rtype: :class:`telebot.types.KeyboardButtonRequestUser` + :rtype: :class:`telebot.types.KeyboardButtonRequestUsers` """ - def __init__(self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None) -> None: + def __init__(self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, max_quantity: Optional[int]=None) -> None: self.request_id: int = request_id self.user_is_bot: Optional[bool] = user_is_bot self.user_is_premium: Optional[bool] = user_is_premium + self.max_quantity: Optional[int] = max_quantity def to_dict(self) -> dict: data = {'request_id': self.request_id} @@ -2373,8 +2376,11 @@ def to_dict(self) -> dict: data['user_is_bot'] = self.user_is_bot if self.user_is_premium is not None: data['user_is_premium'] = self.user_is_premium + if self.max_quantity is not None: + data['max_quantity'] = self.max_quantity return data +KeyboardButtonRequestUser = KeyboardButtonRequestUsers class KeyboardButtonRequestChat(Dictionaryable): """ @@ -2476,7 +2482,7 @@ class KeyboardButton(Dictionaryable, JsonSerializable): :param request_user: Optional. If specified, pressing the button will open a list of suitable users. Tapping on any user will send their identifier to the bot in a “user_shared” service message. Available in private chats only. - :type request_user: :class:`telebot.types.KeyboardButtonRequestUser` + :type request_user: :class:`telebot.types.KeyboardButtonRequestUsers` :param request_chat: Optional. If specified, pressing the button will open a list of suitable chats. Tapping on a chat will send its identifier to the bot in a “chat_shared” service message. Available in private chats only. @@ -2487,15 +2493,18 @@ class KeyboardButton(Dictionaryable, JsonSerializable): """ def __init__(self, text: str, request_contact: Optional[bool]=None, request_location: Optional[bool]=None, request_poll: Optional[KeyboardButtonPollType]=None, - web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUser]=None, - request_chat: Optional[KeyboardButtonRequestChat]=None): + web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUsers]=None, + request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None): self.text: str = text self.request_contact: bool = request_contact self.request_location: bool = request_location self.request_poll: KeyboardButtonPollType = request_poll self.web_app: WebAppInfo = web_app - self.request_user: KeyboardButtonRequestUser = request_user + self.request_user: KeyboardButtonRequestUsers = request_user self.request_chat: KeyboardButtonRequestChat = request_chat + self.request_users: KeyboardButtonRequestUsers = request_users + if request_user is not None: + self.request_users = request_user def to_json(self): @@ -7565,7 +7574,7 @@ def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str class UserShared(JsonDeserializable): """ This object contains information about the user whose identifier was shared with the bot using a - `telebot.types.KeyboardButtonRequestUser` button. + `telebot.types.KeyboardButtonRequestUsers` button. Telegram documentation: https://core.telegram.org/bots/api#usershared From 350f7fea32188f5a4378a8e8b9ecc5b32bda3dd9 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 00:03:14 +0500 Subject: [PATCH 073/480] Added the class UsersShared. Replaced the field user_shared in the class Message with the field users_shared. --- telebot/types.py | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 13a4333b8..f68045d23 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -954,8 +954,8 @@ class Message(JsonDeserializable): the payment. More about payments » :type successful_payment: :class:`telebot.types.SuccessfulPayment` - :param user_shared: Optional. Service message: a user was shared with the bot - :type user_shared: :class:`telebot.types.UserShared` + :param users_shared: Optional. Service message: a user was shared with the bot + :type users_shared: :class:`telebot.types.UserShared` :param chat_shared: Optional. Service message: a chat was shared with the bot :type chat_shared: :class:`telebot.types.ChatShared` @@ -1209,9 +1209,9 @@ def de_json(cls, json_string): if 'write_access_allowed' in obj: opts['write_access_allowed'] = WriteAccessAllowed.de_json(obj['write_access_allowed']) content_type = 'write_access_allowed' - if 'user_shared' in obj: - opts['user_shared'] = UserShared.de_json(obj['user_shared']) - content_type = 'user_shared' + if 'users_shared' in obj: + opts['users_shared'] = UserShared.de_json(obj['users_shared']) + content_type = 'users_shared' # COMPATIBILITY BROKEN! if 'chat_shared' in obj: opts['chat_shared'] = ChatShared.de_json(obj['chat_shared']) content_type = 'chat_shared' @@ -1324,7 +1324,8 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.general_forum_topic_hidden: Optional[GeneralForumTopicHidden] = None self.general_forum_topic_unhidden: Optional[GeneralForumTopicUnhidden] = None self.write_access_allowed: Optional[WriteAccessAllowed] = None - self.user_shared: Optional[UserShared] = None + self.users_shared: Optional[UserShared] = None + self.user_shared: Optional[UserShared] = self.users_shared self.chat_shared: Optional[ChatShared] = None self.story: Optional[Story] = None self.external_reply: Optional[ExternalReplyInfo] = None @@ -8742,3 +8743,35 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) +class UsersShared(JsonDeserializable): + """ + This object contains information about the users whose identifiers were shared with the bot + using a KeyboardButtonRequestUsers button. + + Telegram documentation: https://core.telegram.org/bots/api#usersshared + + :param request_id: Identifier of the request + :type request_id: :obj:`int` + + :param user_ids: Identifiers of the shared users. These numbers may have more than 32 significant bits + and some programming languages may have difficulty/silent defects in interpreting them. + But they have at most 52 significant bits, so 64-bit integers or double-precision float + types are safe for storing these identifiers. The bot may not have access to the users and + could be unable to use these identifiers unless the users are already known to the bot by + some other means. + :type user_ids: :obj:`list` of :obj:`int` + + :return: Instance of the class + :rtype: :class:`UsersShared` + """ + + def __init__(self, request_id, user_ids): + self.request_id = request_id + self.user_ids = user_ids + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) \ No newline at end of file From e1c92237a69e758f028fc0a59e2c548ccca12925 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 12:42:51 +0500 Subject: [PATCH 074/480] Chat Boosts full support for handlers; --- telebot/__init__.py | 126 ++++++++++++++++ telebot/async_telebot.py | 123 ++++++++++++++++ telebot/types.py | 259 ++++++++++++++++++++++++++++++++- tests/test_handler_backends.py | 8 +- tests/test_telebot.py | 4 +- 5 files changed, 514 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index daad4a88a..223d679f5 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -229,6 +229,8 @@ def __init__( self.my_chat_member_handlers = [] self.chat_member_handlers = [] self.chat_join_request_handlers = [] + self.chat_boost_handlers = [] + self.removed_chat_boost_handlers = [] self.custom_filters = {} self.state_handlers = [] @@ -684,6 +686,8 @@ def process_new_updates(self, updates: List[types.Update]): new_my_chat_members = None new_chat_members = None new_chat_join_request = None + removed_chat_boosts = None + chat_boosts = None for update in updates: if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares: @@ -747,6 +751,12 @@ def process_new_updates(self, updates: List[types.Update]): if update.message_reaction_count: if message_reaction_counts is None: message_reaction_counts = [] message_reaction_counts.append(update.message_reaction_count) + if update.chat_boost: + if chat_boosts is None: chat_boosts = [] + chat_boosts.append(update.chat_boost) + if update.removed_chat_boost: + if removed_chat_boosts is None: removed_chat_boosts = [] + removed_chat_boosts.append(update.removed_chat_boost) if new_messages: self.process_new_messages(new_messages) @@ -780,6 +790,10 @@ def process_new_updates(self, updates: List[types.Update]): self.process_new_message_reaction(new_message_reactions) if message_reaction_counts: self.process_new_message_reaction_count(message_reaction_counts) + if chat_boosts: + self.process_new_chat_boost(chat_boosts) + if removed_chat_boosts: + self.process_new_removed_chat_boost(removed_chat_boosts) def process_new_messages(self, new_messages): """ @@ -880,6 +894,19 @@ def process_new_chat_join_request(self, chat_join_request): """ self._notify_command_handlers(self.chat_join_request_handlers, chat_join_request, 'chat_join_request') + def process_new_chat_boost(self, chat_boosts): + """ + :meta private: + """ + self._notify_command_handlers(self.chat_boost_handlers, chat_boosts, 'chat_boost') + + def process_new_removed_chat_boost(self, removed_chat_boosts): + """ + :meta private: + """ + self._notify_command_handlers(self.removed_chat_boost_handlers, removed_chat_boosts, 'removed_chat_boost') + + def process_middlewares(self, update): """ :meta private: @@ -7209,6 +7236,105 @@ def register_chat_join_request_handler(self, callback: Callable, func: Optional[ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chat_join_request_handler(handler_dict) + def chat_boost_handler(self, func=None, **kwargs): + """ + Handles new incoming chat boost state. + it passes :class:`telebot.types.ChatBoostUpdated` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_chat_boost_handler(handler_dict) + return handler + + return decorator + + def add_chat_boost_handler(self, handler_dict): + """ + Adds a chat_boost handler. + Note that you should use register_chat_boost_handler to add chat_boost_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.chat_boost_handlers.append(handler_dict) + + def register_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + """ + Registers chat boost handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_chat_boost_handler(handler_dict) + + def removed_chat_boost_handler(self, func=None, **kwargs): + """ + Handles new incoming chat boost state. + it passes :class:`telebot.types.ChatBoostRemoved` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_removed_chat_boost_handler(handler_dict) + return handler + + return decorator + + def add_removed_chat_boost_handler(self, handler_dict): + """ + Adds a removed_chat_boost handler. + Note that you should use register_removed_chat_boost_handler to add removed_chat_boost_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.removed_chat_boost_handlers.append(handler_dict) + + def register_removed_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + """ + Registers removed chat boost handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_removed_chat_boost_handler(handler_dict) + + def _test_message_handler(self, message_handler, message): """ Test message handler diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 4adc7b424..34cd56051 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -171,6 +171,8 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.my_chat_member_handlers = [] self.chat_member_handlers = [] self.chat_join_request_handlers = [] + self.removed_chat_boost_handlers = [] + self.chat_boost_handlers = [] self.custom_filters = {} self.state_handlers = [] self.middlewares = [] @@ -590,6 +592,8 @@ async def process_new_updates(self, updates: List[types.Update]): new_my_chat_members = None new_chat_members = None chat_join_request = None + removed_chat_boost_handlers = None + chat_boost_handlers = None for update in updates: logger.debug('Processing updates: {0}'.format(update)) if update.message: @@ -640,6 +644,12 @@ async def process_new_updates(self, updates: List[types.Update]): if update.message_reaction_count: if new_message_reaction_count_handlers is None: new_message_reaction_count_handlers = [] new_message_reaction_count_handlers.append(update.message_reaction_count) + if update.chat_boost: + if chat_boost_handlers is None: chat_boost_handlers = [] + chat_boost_handlers.append(update.chat_boost) + if update.removed_chat_boost: + if removed_chat_boost_handlers is None: removed_chat_boost_handlers = [] + removed_chat_boost_handlers.append(update.removed_chat_boost) if new_messages: @@ -674,6 +684,8 @@ async def process_new_updates(self, updates: List[types.Update]): await self.process_new_message_reaction(new_message_reactions) if new_message_reaction_count_handlers: await self.process_new_message_reaction_count(new_message_reaction_count_handlers) + if chat_boost_handlers: + await self.process_new_chat_boost(chat_boost_handlers) async def process_new_messages(self, new_messages): """ @@ -772,6 +784,18 @@ async def process_chat_join_request(self, chat_join_request): """ await self._process_updates(self.chat_join_request_handlers, chat_join_request, 'chat_join_request') + async def process_new_chat_boost(self, chat_boost): + """ + :meta private: + """ + await self._process_updates(self.chat_boost_handlers, chat_boost, 'chat_boost') + + async def process_new_removed_chat_boost(self, removed_chat_boost): + """ + :meta private: + """ + await self._process_updates(self.removed_chat_boost_handlers, removed_chat_boost, 'removed_chat_boost') + async def _get_middlewares(self, update_type): """ :meta private: @@ -2002,6 +2026,105 @@ def register_chat_join_request_handler(self, callback: Callable[[Any], Awaitable handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chat_join_request_handler(handler_dict) + + def chat_boost_handler(self, func=None, **kwargs): + """ + Handles new incoming chat boost state. + it passes :class:`telebot.types.ChatBoostUpdated` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_chat_boost_handler(handler_dict) + return handler + + return decorator + + def add_chat_boost_handler(self, handler_dict): + """ + Adds a chat_boost handler. + Note that you should use register_chat_boost_handler to add chat_boost_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.chat_boost_handlers.append(handler_dict) + + def register_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + """ + Registers chat boost handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_chat_boost_handler(handler_dict) + + def removed_chat_boost_handler(self, func=None, **kwargs): + """ + Handles new incoming chat boost state. + it passes :class:`telebot.types.ChatBoostRemoved` object. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_removed_chat_boost_handler(handler_dict) + return handler + + return decorator + + def add_removed_chat_boost_handler(self, handler_dict): + """ + Adds a removed_chat_boost handler. + Note that you should use register_removed_chat_boost_handler to add removed_chat_boost_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.removed_chat_boost_handlers.append(handler_dict) + + def register_removed_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + """ + Registers removed chat boost handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_removed_chat_boost_handler(handler_dict) + @staticmethod def _build_handler_dict(handler, pass_bot=False, **filters): """ diff --git a/telebot/types.py b/telebot/types.py index f68045d23..dc7c15f49 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -173,6 +173,12 @@ class Update(JsonDeserializable): can_invite_users administrator right in the chat to receive these updates. :type chat_join_request: :class:`telebot.types.ChatJoinRequest` + :param chat_boost: Optional. A chat boost was added or changed. The bot must be an administrator in the chat to receive these updates. + :type chat_boost: :class:`telebot.types.ChatBoost` + + :param removed_chat_boost: Optional. A chat boost was removed. The bot must be an administrator in the chat to receive these updates. + :type removed_chat_boost: :class:`telebot.types.RemovedChatBoost` + :return: Instance of the class :rtype: :class:`telebot.types.Update` @@ -198,13 +204,15 @@ def de_json(cls, json_string): chat_join_request = ChatJoinRequest.de_json(obj.get('chat_join_request')) message_reaction = MessageReactionUpdated.de_json(obj.get('message_reaction')) message_reaction_count = MessageReactionCountUpdated.de_json(obj.get('message_reaction_count')) + removed_chat_boost = ChatBoostRemoved.de_json(obj.get('removed_chat_boost')) + chat_boost = ChatBoost.de_json(obj.get('chat_boost')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count): + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost): self.update_id = update_id self.message = message self.edited_message = edited_message @@ -222,6 +230,8 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.chat_join_request = chat_join_request self.message_reaction = message_reaction self.message_reaction_count = message_reaction_count + self.removed_chat_boost = removed_chat_boost + self.chat_boost = chat_boost class ChatMemberUpdated(JsonDeserializable): @@ -8774,4 +8784,247 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - return cls(**obj) \ No newline at end of file + return cls(**obj) + + +class ChatBoostUpdated(JsonDeserializable): + """ + This object represents a boost added to a chat or changed. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostupdated + + :param chat: Chat which was boosted + :type chat: :class:`Chat` + + :param boost: Infomation about the chat boost + :type boost: :class:`ChatBoost` + + :return: Instance of the class + :rtype: :class:`ChatBoostUpdated` + """ + + def __init__(self, chat, boost): + self.chat = chat + self.boost = boost + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + obj['chat'] = Chat.de_json(obj.get('chat')) + obj['boost'] = ChatBoost.de_json(obj.get('boost')) + + return cls(**obj) + +# ChatBoostRemoved +# This object represents a boost removed from a chat. + +# Field Type Description +# chat Chat Chat which was boosted +# boost_id String Unique identifier of the boost +# remove_date Integer Point in time (Unix timestamp) when the boost was removed +# source ChatBoostSource Source of the removed boost + +class ChatBoostRemoved(JsonDeserializable): + """ + This object represents a boost removed from a chat. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostremoved + + :param chat: Chat which was boosted + :type chat: :class:`Chat` + + :param boost_id: Unique identifier of the boost + :type boost_id: :obj:`str` + + :param remove_date: Point in time (Unix timestamp) when the boost was removed + :type remove_date: :obj:`int` + + :param source: Source of the removed boost + :type source: :class:`ChatBoostSource` + + :return: Instance of the class + :rtype: :class:`ChatBoostRemoved` + """ + + def __init__(self, chat, boost_id, remove_date, source): + self.chat = chat + self.boost_id = boost_id + self.remove_date = remove_date + self.source = source + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + obj['chat'] = Chat.de_json(obj.get('chat')) + obj['source'] = ChatBoostSource.de_json(obj.get('source')) + + return cls(**obj) + +class ChatBoostSource(JsonDeserializable): + """ + This object describes the source of a chat boost. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostsource + + :param source: Source of the boost + :type source: :obj:`str` + + :return: Instance of the class + :rtype: :class:`ChatBoostSource` + """ + + def __init__(self, source): + self.source = source + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + return cls(**cls.check_json(json_string)) + + +class ChatBoostSourcePremium(ChatBoostSource): + """ + The boost was obtained by subscribing to Telegram Premium or by gifting a Telegram Premium subscription to another user. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostsourcepremium + + :param source: Source of the boost, always “premium” + :type source: :obj:`str` + + :param user: User that boosted the chat + :type user: :class:`User` + + :return: Instance of the class + :rtype: :class:`ChatBoostSourcePremium` + """ + + def __init__(self, user): + super().__init__('premium') + self.user = user + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + user = User.de_json(json.dumps(obj['user'])) + return cls(user) + +class ChatBoostSourceGiftCode(ChatBoostSource): + """ + The boost was obtained by the creation of Telegram Premium gift codes to boost a chat. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostsourcegiftcode + + :param source: Source of the boost, always “gift_code” + :type source: :obj:`str` + + :param user: User for which the gift code was created + :type user: :class:`User` + + :return: Instance of the class + :rtype: :class:`ChatBoostSourceGiftCode` + """ + + def __init__(self, user): + super().__init__('gift_code') + self.user = user + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + user = User.de_json(json.dumps(obj['user'])) + return cls(user) + +class ChatBoostSourceGiveaway(ChatBoostSource): + """ + The boost was obtained by the creation of a Telegram Premium giveaway. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostsourcegiveaway + + :param source: Source of the boost, always “giveaway” + :type source: :obj:`str` + + :param giveaway_message_id: Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet. + :type giveaway_message_id: :obj:`int` + + :param user: User that won the prize in the giveaway if any + :type user: :class:`User` + + :param is_unclaimed: True, if the giveaway was completed, but there was no user to win the prize + :type is_unclaimed: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`ChatBoostSourceGiveaway` + """ + + def __init__(self, giveaway_message_id, user=None, is_unclaimed=None): + super().__init__('giveaway') + self.giveaway_message_id = giveaway_message_id + self.user = user + self.is_unclaimed = is_unclaimed + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + user = User.de_json(json.dumps(obj['user'])) if 'user' in obj else None + return cls(obj['giveaway_message_id'], user, obj.get('is_unclaimed')) + +#ChatBoost +# This object contains information about a chat boost. + +# Field Type Description +# boost_id String Unique identifier of the boost +# add_date Integer Point in time (Unix timestamp) when the chat was boosted +# expiration_date Integer Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium subscription is prolonged +# source ChatBoostSource Source of the added boost + +class ChatBoost(JsonDeserializable): + """ + This object contains information about a chat boost. + + Telegram documentation: https://core.telegram.org/bots/api#chatboost + + :param boost_id: Unique identifier of the boost + :type boost_id: :obj:`str` + + :param add_date: Point in time (Unix timestamp) when the chat was boosted + :type add_date: :obj:`int` + + :param expiration_date: Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium subscription is prolonged + :type expiration_date: :obj:`int` + + :param source: Source of the added boost + :type source: :class:`ChatBoostSource` + + :return: Instance of the class + :rtype: :class:`ChatBoost` + """ + + def __init__(self, boost_id, add_date, expiration_date, source): + self.boost_id = boost_id + self.add_date = add_date + self.expiration_date = expiration_date + self.source: ChatBoostSource = source + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + + obj['source'] = ChatBoostSource.de_json(json.dumps(obj['source'])) + + return cls(**obj) + diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index ef22e8520..fa893c489 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -67,9 +67,11 @@ def update_type(message): chat_join_request = None message_reaction = None message_reaction_count = None + chat_boost = None + chat_boost_removed = None return types.Update(1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed) @pytest.fixture() @@ -89,9 +91,11 @@ def reply_to_message_update_type(reply_to_message): chat_join_request = None message_reaction = None message_reaction_count = None + chat_boost = None + chat_boost_removed = None return types.Update(1001234038284, reply_to_message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, - poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) + poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed) def next_handler(message): diff --git a/tests/test_telebot.py b/tests/test_telebot.py index c1f08f8f0..52adbc2fe 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -544,9 +544,11 @@ def create_message_update(text): chat_join_request = None message_reaction = None message_reaction_count = None + chat_boost = None + chat_boost_removed = None return types.Update(-1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed) def test_is_string_unicode(self): s1 = u'string' From 137ea69e88e8808ac1bc1b21d9e6bf010462eeee Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 12:48:00 +0500 Subject: [PATCH 075/480] get_user_chat_boosts for sync and async; +UserChatBoosts --- telebot/__init__.py | 21 ++++++++++++++++++++- telebot/apihelper.py | 5 +++++ telebot/async_telebot.py | 27 +++++++++++++++++++++++++++ telebot/asyncio_helper.py | 4 ++++ telebot/types.py | 26 ++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 223d679f5..e9120066a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -905,7 +905,7 @@ def process_new_removed_chat_boost(self, removed_chat_boosts): :meta private: """ self._notify_command_handlers(self.removed_chat_boost_handlers, removed_chat_boosts, 'removed_chat_boost') - + def process_middlewares(self, update): """ @@ -5069,6 +5069,25 @@ def answer_callback_query( :rtype: :obj:`bool` """ return apihelper.answer_callback_query(self.token, callback_query_id, text, show_alert, url, cache_time) + + def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts: + """ + Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. + + Telegram documentation: https://core.telegram.org/bots/api#getuserchatboosts + + :param chat_id: Unique identifier for the target chat or username of the target channel + :type chat_id: :obj:`int` | :obj:`str` + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :return: On success, a UserChatBoosts object is returned. + :rtype: :class:`telebot.types.UserChatBoosts` + """ + + result = apihelper.get_user_chat_boosts(self.token, chat_id, user_id) + return types.UserChatBoosts.de_json(result) def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None): """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 88a4e697a..a50b61830 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1616,6 +1616,11 @@ def answer_callback_query(token, callback_query_id, text=None, show_alert=None, return _make_request(token, method_url, params=payload, method='post') +def get_user_chat_boosts(token, chat_id, user_id): + method_url = 'getUserChatBoosts' + payload = {'chat_id': chat_id, 'user_id': user_id} + return _make_request(token, method_url, params=payload) + def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None, button=None): method_url = 'answerInlineQuery' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 34cd56051..6e02ce19a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6135,6 +6135,33 @@ async def answer_callback_query( :rtype: :obj:`bool` """ return await asyncio_helper.answer_callback_query(self.token, callback_query_id, text, show_alert, url, cache_time) + +# getUserChatBoosts +# Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. + +# Parameter Type Required Description +# chat_id Integer or String Yes Unique identifier for the chat or username of the channel (in the format @channelusername) +# user_id Integer Yes Unique identifier of the target user + + async def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts: + """ + Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. + + Telegram documentation: https://core.telegram.org/bots/api#getuserchatboosts + + :param chat_id: Unique identifier for the target chat or username of the target channel + :type chat_id: :obj:`int` | :obj:`str` + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :return: On success, a UserChatBoosts object is returned. + :rtype: :class:`telebot.types.UserChatBoosts` + """ + + result = await asyncio_helper.get_user_chat_boosts(self.token, chat_id, user_id) + return types.UserChatBoosts.de_json(result) + async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None): """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index ae119078e..5da6859cf 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1591,6 +1591,10 @@ async def answer_callback_query(token, callback_query_id, text=None, show_alert= payload['cache_time'] = cache_time return await _process_request(token, method_url, params=payload, method='post') +async def get_user_chat_boosts(token, chat_id, user_id): + method_url = 'getUserChatBoosts' + payload = {'chat_id': chat_id, 'user_id': user_id} + return await _process_request(token, method_url, params=payload) async def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None, button=None): diff --git a/telebot/types.py b/telebot/types.py index dc7c15f49..fe5241c17 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9028,3 +9028,29 @@ def de_json(cls, json_string): return cls(**obj) +class UserChatBoosts(JsonDeserializable): + """ + This object represents a list of boosts added to a chat by a user. + + Telegram documentation: https://core.telegram.org/bots/api#userchatboosts + + :param boosts: The list of boosts added to the chat by the user + :type boosts: :obj:`list` of :class:`ChatBoost` + + :return: Instance of the class + :rtype: :class:`UserChatBoosts` + """ + + def __init__(self, boosts): + self.boosts: ChatBoost = boosts + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + + obj = cls.check_json(json_string) + obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj.get('boosts', [])] + + return cls(**obj) + \ No newline at end of file From ab2d1facd688d9d3e12f1204fad83070788ed873 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 12:59:39 +0500 Subject: [PATCH 076/480] Giveaways full support: start and end of giveaways, and information about winners --- telebot/types.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index fe5241c17..058ffa96c 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1003,6 +1003,18 @@ class Message(JsonDeserializable): :param general_forum_topic_unhidden: Optional. Service message: the 'General' forum topic unhidden :type general_forum_topic_unhidden: :class:`telebot.types.GeneralForumTopicUnhidden` + :param giveaway_created: Optional. Service message: a giveaway has been created + :type giveaway_created: :class:`telebot.types.GiveawayCreated` + + :param giveaway: Optional. The message is a scheduled giveaway message + :type giveaway: :class:`telebot.types.Giveaway` + + :param giveaway_winners: Optional. Service message: giveaway winners(public winners) + :type giveaway_winners: :class:`telebot.types.GiveawayWinners` + + :param giveaway_completed: Optional. Service message: giveaway completed, without public winners + :type giveaway_completed: :class:`telebot.types.GiveawayCompleted` + :param video_chat_scheduled: Optional. Service message: video chat scheduled :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` @@ -1238,6 +1250,20 @@ def de_json(cls, json_string): if 'link_preview_options' in obj: opts['link_preview_options'] = LinkPreviewOptions.de_json(obj['link_preview_options']) + if 'giveaway_created' in obj: + opts['giveaway_created'] = GiveawayCreated.de_json(obj['giveaway_created']) + content_type = 'giveaway_created' + if 'giveaway' in obj: + opts['giveaway'] = Giveaway.de_json(obj['giveaway']) + content_type = 'giveaway' + if 'giveaway_winners' in obj: + opts['giveaway_winners'] = GiveawayWinners.de_json(obj['giveaway_winners']) + content_type = 'giveaway_winners' + if 'giveaway_completed' in obj: + opts['giveaway_completed'] = GiveawayCompleted.de_json(obj['giveaway_completed']) + content_type = 'giveaway_completed' + + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1341,6 +1367,11 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.external_reply: Optional[ExternalReplyInfo] = None self.quote: Optional[TextQuote] = None self.LinkPreviewOptions: Optional[LinkPreviewOptions] = None + self.giveaway_created: Optional[GiveawayCreated] = None + self.giveaway: Optional[Giveaway] = None + self.giveaway_winners: Optional[GiveawayWinners] = None + self.giveaway_completed: Optional[GiveawayCompleted] = None + for key in options: setattr(self, key, options[key]) @@ -8634,7 +8665,45 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: self.was_refunded: Optional[bool] = was_refunded self.prize_description: Optional[str] = prize_description +class GiveawayCompleted(JsonDeserializable): + """ + This object represents a service message about the completion of a giveaway without public winners. + + Telegram documentation: https://core.telegram.org/bots/api#giveawaycompleted + + :param winner_count: Number of winners in the giveaway + :type winner_count: :obj:`int` + + :param unclaimed_prize_count: Optional. Number of undistributed prizes + :type unclaimed_prize_count: :obj:`int` + + :param giveaway_message: Optional. Message with the giveaway that was completed, if it wasn't deleted + :type giveaway_message: :class:`Message` + + :return: Instance of the class + :rtype: :class:`GiveawayCompleted` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + obj['giveaway_message'] = Message.de_json(obj.get('giveaway_message')) + + return cls(**obj) + + def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = None, + giveaway_message: Optional[Message] = None) -> None: + self.winner_count: int = winner_count + self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count + self.giveaway_message: Optional[Message] = giveaway_message + +class GiveawayCreated(JsonDeserializable): + """ + This object represents a service message about the creation of a scheduled giveaway. Currently holds no information. + """ class TextQuote(JsonDeserializable): """ From e290f27f6a6ec0cc8910880b5e200d4e9b366e73 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 13:11:31 +0500 Subject: [PATCH 077/480] Added the fields has_visible_story, accent_color_id, background_custom_emoji_id, profile_accent_color_id, and profile_background_custom_emoji_id to the class Chat. --- telebot/types.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 058ffa96c..66a0e19f4 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -565,6 +565,22 @@ class Chat(JsonDeserializable): Returned only in getChat. :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType` + :param accent_color_id: Optional. Optional. Identifier of the accent color for the chat name and backgrounds of the chat photo, + reply header, and link preview. See accent colors for more details. Returned only in getChat. Always returned in getChat. + :type accent_color_id: :obj:`int` + + :param background_custom_emoji_id: Optional. Custom emoji identifier of emoji chosen by the chat for the reply header + and link preview background. Returned only in getChat. + :type background_custom_emoji_id: :obj:`str` + + :param profile_accent_color_id: Optional. Identifier of the accent color for the chat's profile background. + See profile accent colors for more details. Returned only in getChat. + :type profile_accent_color_id: :obj:`int` + + :param profile_background_custom_emoji_id: Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. + Returned only in getChat. + :type profile_background_custom_emoji_id: :obj:`str` + :param emoji_status_custom_emoji_id: Optional. Custom emoji identifier of emoji status of the other party in a private chat. Returned only in getChat. :type emoji_status_custom_emoji_id: :obj:`str` @@ -626,6 +642,10 @@ class Chat(JsonDeserializable): chats. Returned only in getChat. :type has_protected_content: :obj:`bool` + :param has_visible_history: Optional. True, if new chat members will have access to old messages; + available only to chat administrators. Returned only in getChat. + :type has_visible_history: :obj:`bool` + :param sticker_set_name: Optional. For supergroups, name of group sticker set. Returned only in getChat. :type sticker_set_name: :obj:`str` @@ -671,7 +691,8 @@ def __init__(self, id, type, title=None, username=None, first_name=None, join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, - available_reactions=None,**kwargs): + available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, + profile_background_custom_emoji_id=None, has_visible_history=None,**kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -702,6 +723,12 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.has_aggressive_anti_spam_enabled: bool = has_aggressive_anti_spam_enabled self.emoji_status_expiration_date: int = emoji_status_expiration_date self.available_reactions: List[ReactionType] = available_reactions + self.accent_color_id: int = accent_color_id + self.background_custom_emoji_id: str = background_custom_emoji_id + self.profile_accent_color_id: int = profile_accent_color_id + self.profile_background_custom_emoji_id: str = profile_background_custom_emoji_id + self.has_visible_history: bool = has_visible_history + class MessageID(JsonDeserializable): From af6f485ba6e3a50d7770562c74746ec2f83cf305 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 13:19:02 +0500 Subject: [PATCH 078/480] Added the class MessageOrigin and replaced the fields forward_from, forward_from_chat, forward_from_message_id, forward_signature, forward_sender_name, and forward_date with the field forward_origin of type MessageOrigin in the class Message. --- telebot/types.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 66a0e19f4..63b69b14a 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -833,6 +833,9 @@ class Message(JsonDeserializable): :param forward_date: Optional. For forwarded messages, date the original message was sent in Unix time :type forward_date: :obj:`int` + :forward_origin: Optional. For forwarded messages, information about the original message; + :type forward_origin: :class:`telebot.types.MessageOrigin` + :param is_topic_message: Optional. True, if the message is sent to a forum topic :type is_topic_message: :obj:`bool` @@ -1289,8 +1292,8 @@ def de_json(cls, json_string): if 'giveaway_completed' in obj: opts['giveaway_completed'] = GiveawayCompleted.de_json(obj['giveaway_completed']) content_type = 'giveaway_completed' - - + if 'message_origin' in obj: + opts['message_origin'] = MessageOrigin.de_json(obj['message_origin']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1398,6 +1401,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.giveaway: Optional[Giveaway] = None self.giveaway_winners: Optional[GiveawayWinners] = None self.giveaway_completed: Optional[GiveawayCompleted] = None + self.forward_origin: Optional[MessageOrigin] = None for key in options: From e94d5cecbc1602989fd8a7daa0623f5e139454fb Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 13:31:54 +0500 Subject: [PATCH 079/480] Added InaccessibleMessage support, not sure on the implementation for pinned_message and answer_callback_query --- telebot/types.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 63b69b14a..f47670917 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9153,4 +9153,39 @@ def de_json(cls, json_string): obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj.get('boosts', [])] return cls(**obj) + + +class InaccessibleMessage(JsonDeserializable): + """ + This object describes a message that was deleted or is otherwise inaccessible to the bot. + + Telegram documentation: https://core.telegram.org/bots/api#inaccessiblemessage + + :param chat: Chat the message belonged to + :type chat: :class:`Chat` + + :param message_id: Unique message identifier inside the chat + :type message_id: :obj:`int` + + :param date: Always 0. The field can be used to differentiate regular and inaccessible messages. + :type date: :obj:`int` + + :return: Instance of the class + :rtype: :class:`InaccessibleMessage` + """ + + def __init__(self, chat, message_id, date): + self.chat = chat + self.message_id = message_id + self.date = date + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + + obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj.get('chat')) + + return cls(**obj) \ No newline at end of file From 456a9ed3c8b6026cd860ab2fdacf8395f8270b2a Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 14:00:16 +0500 Subject: [PATCH 080/480] Minor utils edit that adds all update types --- telebot/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/util.py b/telebot/util.py index 174239d35..9f0c7ab4c 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -45,7 +45,7 @@ update_types = [ "message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member", - "chat_join_request", "message_reaction", "message_reaction_count" + "chat_join_request", "message_reaction", "message_reaction_count", "chat_boost", "removed_chat_boost", ] From 39abb9d555a2681c74ae07bb290be779164bd829 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 14:45:28 +0500 Subject: [PATCH 081/480] Fix a typo --- telebot/async_telebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 6e02ce19a..7e7ae4689 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -581,7 +581,7 @@ async def process_new_updates(self, updates: List[types.Update]): new_channel_posts = None new_edited_channel_posts = None new_message_reactions = None - mew_message_reaction_count_handlers = None + new_message_reaction_count_handlers = None new_inline_queries = None new_chosen_inline_results = None new_callback_queries = None From 87404d3f2a738a04bd108c17fdbab2f894c69067 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 14:52:58 +0500 Subject: [PATCH 082/480] Set func=None by default for new handlers; --- telebot/__init__.py | 8 ++++---- telebot/async_telebot.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index e9120066a..39332c166 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6639,7 +6639,7 @@ def register_edited_channel_post_handler(self, callback: Callable, content_types self.add_edited_channel_post_handler(handler_dict) - def message_reaction_handler(self, func, **kwargs): + def message_reaction_handler(self, func=None, **kwargs): """ Handles new incoming message reaction. As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. @@ -6670,7 +6670,7 @@ def add_message_reaction_handler(self, handler_dict): """ self.message_reaction_handlers.append(handler_dict) - def register_message_reaction_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): + def register_message_reaction_handler(self, callback: Callable, func: Callable=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers message reaction handler. @@ -6690,7 +6690,7 @@ def register_message_reaction_handler(self, callback: Callable, func: Callable, handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_message_reaction_handler(handler_dict) - def message_reaction_count_handler(self, func, **kwargs): + def message_reaction_count_handler(self, func=None, **kwargs): """ Handles new incoming message reaction count. As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. @@ -6721,7 +6721,7 @@ def add_message_reaction_count_handler(self, handler_dict): """ self.message_reaction_count_handlers.append(handler_dict) - def register_message_reaction_count_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): + def register_message_reaction_count_handler(self, callback: Callable, func: Callable=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers message reaction count handler. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 7e7ae4689..658443124 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -1397,7 +1397,7 @@ def register_edited_channel_post_handler(self, callback: Callable[[Any], Awaitab **kwargs) self.add_edited_channel_post_handler(handler_dict) - def messsage_reaction_handler(self, func, **kwargs): + def message_reaction_handler(self, func=None, **kwargs): """ Handles new incoming message reaction. As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. @@ -1429,7 +1429,7 @@ def add_message_reaction_handler(self, handler_dict): """ self.message_reaction_handlers.append(handler_dict) - def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable], func: Callable, pass_bot: Optional[bool]=False, **kwargs): + def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable], func: Callable=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers message reaction handler. @@ -1449,7 +1449,7 @@ def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable] handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_message_reaction_handler(handler_dict) - def message_reaction_count_handler(self, func, **kwargs): + def message_reaction_count_handler(self, func=None, **kwargs): """ Handles new incoming message reaction count. As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. @@ -1481,7 +1481,7 @@ def add_message_reaction_count_handler(self, handler_dict): """ self.message_reaction_count_handlers.append(handler_dict) - def register_message_reaction_count_handler(self, callback: Callable[[Any], Awaitable], func: Callable, pass_bot: Optional[bool]=False, **kwargs): + def register_message_reaction_count_handler(self, callback: Callable[[Any], Awaitable], func: Callable=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers message reaction count handler. From bc8120ed4b6910b6b1f019ef62b94206b69812f4 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 15:14:25 +0500 Subject: [PATCH 083/480] Fix issues related with reactions handlers --- telebot/apihelper.py | 2 +- telebot/asyncio_helper.py | 2 +- telebot/types.py | 22 +++++++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index a50b61830..3558219f0 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -335,7 +335,7 @@ def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None) method_url = r'setMessageReaction' payload = {'chat_id': chat_id, 'message_id': message_id} if reaction: - payload['reaction'] = reaction + payload['reaction'] = json.dumps([r.to_dict() for r in reaction]) if is_big is not None: payload['is_big'] = is_big return _make_request(token, method_url, params=payload) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 5da6859cf..872fb591d 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -320,7 +320,7 @@ async def set_message_reaction(token, chat_id, message_id, reaction=None, is_big method_url = r'setMessageReaction' payload = {'chat_id': chat_id, 'message_id': message_id} if reaction: - payload['reaction'] = reaction + payload['reaction'] = json.dumps([r.to_dict() for r in reaction]) if is_big is not None: payload['is_big'] = is_big return await _process_request(token, method_url, params=payload) diff --git a/telebot/types.py b/telebot/types.py index f47670917..8a9930412 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7986,7 +7986,13 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - return cls(**obj) + # remove type + if obj['type'] == 'emoji': + del obj['type'] + return ReactionTypeEmoji(**obj) + elif obj['type'] == 'custom_emoji': + del obj['type'] + return ReactionTypeCustomEmoji(**obj) def __init__(self, type: str) -> None: self.type: str = type @@ -8028,6 +8034,8 @@ def to_dict(self) -> dict: return json_dict + + class ReactionTypeCustomEmoji(ReactionType): """ @@ -8055,6 +8063,8 @@ def to_dict(self) -> dict: return json_dict + + class MessageReactionUpdated(JsonDeserializable): """ @@ -8092,6 +8102,16 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + + if 'user' in obj: + obj['user'] = User.de_json(obj['user']) + if 'actor_chat' in obj: + obj['actor_chat'] = Chat.de_json(obj['actor_chat']) + obj['old_reaction'] = [ReactionType.de_json(reaction) for reaction in obj['old_reaction']] + obj['new_reaction'] = [ReactionType.de_json(reaction) for reaction in obj['new_reaction']] + if 'chat' in obj: + obj['chat'] = Chat.de_json(obj['chat']) + return cls(**obj) def __init__(self, chat: Chat, message_id: int, date: int, old_reaction: List[ReactionType], new_reaction: List[ReactionType], From f081ec8bc084c0b8be3c87984aa2d2e02922c409 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 30 Dec 2023 15:23:48 +0500 Subject: [PATCH 084/480] Fix de_json for some classes --- telebot/types.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 8a9930412..feb16094a 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8153,6 +8153,10 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + + obj['reactions'] = [ReactionCount.de_json(reaction) for reaction in obj['reactions']] + obj['chat'] = Chat.de_json(obj['chat']) + return cls(**obj) def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[ReactionCount]) -> None: @@ -8183,6 +8187,9 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + + obj['type'] = ReactionType.de_json(obj['type']) + return cls(**obj) def __init__(self, type: ReactionType, total_count: int) -> None: From 05a939bd8dbd449b55def3b3732efef2dbd11d54 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 31 Dec 2023 21:22:49 +0500 Subject: [PATCH 085/480] Fix reply_markup issue with reply_parameters conflict --- telebot/apihelper.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 3558219f0..5f8702533 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -261,7 +261,7 @@ def send_message( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, method='post') @@ -427,7 +427,7 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['disable_notification'] = disable_notification if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if timeout: payload['timeout'] = timeout if protect_content is not None: @@ -449,7 +449,7 @@ def send_dice( payload['disable_notification'] = disable_notification if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: @@ -496,7 +496,7 @@ def send_photo( payload['has_spoiler'] = has_spoiler if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -511,7 +511,7 @@ def send_media_group( payload['disable_notification'] = disable_notification if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if timeout: payload['timeout'] = timeout if protect_content is not None: @@ -553,7 +553,7 @@ def send_location( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -650,7 +650,7 @@ def send_contact( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -712,7 +712,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['has_spoiler'] = has_spoiler if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -752,7 +752,7 @@ def send_animation( payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if width: @@ -796,7 +796,7 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= payload['message_thread_id'] = message_thread_id if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -832,7 +832,7 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark payload['thumbnail'] = thumbnail if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -882,7 +882,7 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['message_thread_id'] = message_thread_id if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -923,7 +923,7 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if method_url == 'sendDocument' and disable_content_type_detection is not None: @@ -1392,7 +1392,7 @@ def send_game( payload['timeout'] = timeout if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: @@ -1544,7 +1544,7 @@ def send_invoice( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: # to json - payload['reply_markup'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) From 52a0314f1d790c2e3b02f89cacb08b1df90577bf Mon Sep 17 00:00:00 2001 From: Badiboy Date: Tue, 2 Jan 2024 22:23:38 +0300 Subject: [PATCH 086/480] Fix naming in Update class Fix "new_" usage. No valuable changes. --- telebot/__init__.py | 82 ++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 39332c166..6c872cda4 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -675,7 +675,7 @@ def process_new_updates(self, updates: List[types.Update]): new_channel_posts = None new_edited_channel_posts = None new_message_reactions = None - message_reaction_counts = None + new_message_reaction_counts = None new_inline_queries = None new_chosen_inline_results = None new_callback_queries = None @@ -686,8 +686,8 @@ def process_new_updates(self, updates: List[types.Update]): new_my_chat_members = None new_chat_members = None new_chat_join_request = None - removed_chat_boosts = None - chat_boosts = None + new_chat_boosts = None + new_removed_chat_boosts = None for update in updates: if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares: @@ -749,14 +749,14 @@ def process_new_updates(self, updates: List[types.Update]): if new_message_reactions is None: new_message_reactions = [] new_message_reactions.append(update.message_reaction) if update.message_reaction_count: - if message_reaction_counts is None: message_reaction_counts = [] - message_reaction_counts.append(update.message_reaction_count) + if new_message_reaction_counts is None: new_message_reaction_counts = [] + new_message_reaction_counts.append(update.message_reaction_count) if update.chat_boost: - if chat_boosts is None: chat_boosts = [] - chat_boosts.append(update.chat_boost) + if new_chat_boosts is None: new_chat_boosts = [] + new_chat_boosts.append(update.chat_boost) if update.removed_chat_boost: - if removed_chat_boosts is None: removed_chat_boosts = [] - removed_chat_boosts.append(update.removed_chat_boost) + if new_removed_chat_boosts is None: new_removed_chat_boosts = [] + new_removed_chat_boosts.append(update.removed_chat_boost) if new_messages: self.process_new_messages(new_messages) @@ -788,12 +788,12 @@ def process_new_updates(self, updates: List[types.Update]): self.process_new_chat_join_request(new_chat_join_request) if new_message_reactions: self.process_new_message_reaction(new_message_reactions) - if message_reaction_counts: - self.process_new_message_reaction_count(message_reaction_counts) - if chat_boosts: - self.process_new_chat_boost(chat_boosts) - if removed_chat_boosts: - self.process_new_removed_chat_boost(removed_chat_boosts) + if new_message_reaction_counts: + self.process_new_message_reaction_count(new_message_reaction_counts) + if new_chat_boosts: + self.process_new_chat_boost(new_chat_boosts) + if new_removed_chat_boosts: + self.process_new_removed_chat_boost(new_removed_chat_boosts) def process_new_messages(self, new_messages): """ @@ -804,35 +804,35 @@ def process_new_messages(self, new_messages): self.__notify_update(new_messages) self._notify_command_handlers(self.message_handlers, new_messages, 'message') - def process_new_edited_messages(self, edited_message): + def process_new_edited_messages(self, new_edited_message): """ :meta private: """ - self._notify_command_handlers(self.edited_message_handlers, edited_message, 'edited_message') + self._notify_command_handlers(self.edited_message_handlers, new_edited_message, 'edited_message') - def process_new_channel_posts(self, channel_post): + def process_new_channel_posts(self, new_channel_post): """ :meta private: """ - self._notify_command_handlers(self.channel_post_handlers, channel_post, 'channel_post') + self._notify_command_handlers(self.channel_post_handlers, new_channel_post, 'channel_post') - def process_new_edited_channel_posts(self, edited_channel_post): + def process_new_edited_channel_posts(self, new_edited_channel_post): """ :meta private: """ - self._notify_command_handlers(self.edited_channel_post_handlers, edited_channel_post, 'edited_channel_post') + self._notify_command_handlers(self.edited_channel_post_handlers, new_edited_channel_post, 'edited_channel_post') - def process_new_message_reaction(self, message_reactions): + def process_new_message_reaction(self, new_message_reactions): """ :meta private: """ - self._notify_command_handlers(self.message_reaction_handlers, message_reactions, 'message_reaction') + self._notify_command_handlers(self.message_reaction_handlers, new_message_reactions, 'message_reaction') - def process_new_message_reaction_count(self, message_reaction_counts): + def process_new_message_reaction_count(self, new_message_reaction_counts): """ :meta private: """ - self._notify_command_handlers(self.message_reaction_count_handlers, message_reaction_counts, 'message_reaction_count') + self._notify_command_handlers(self.message_reaction_count_handlers, new_message_reaction_counts, 'message_reaction_count') def process_new_inline_query(self, new_inline_queries): """ @@ -858,53 +858,53 @@ def process_new_shipping_query(self, new_shipping_queries): """ self._notify_command_handlers(self.shipping_query_handlers, new_shipping_queries, 'shipping_query') - def process_new_pre_checkout_query(self, pre_checkout_queries): + def process_new_pre_checkout_query(self, new_pre_checkout_queries): """ :meta private: """ - self._notify_command_handlers(self.pre_checkout_query_handlers, pre_checkout_queries, 'pre_checkout_query') + self._notify_command_handlers(self.pre_checkout_query_handlers, new_pre_checkout_queries, 'pre_checkout_query') - def process_new_poll(self, polls): + def process_new_poll(self, new_polls): """ :meta private: """ - self._notify_command_handlers(self.poll_handlers, polls, 'poll') + self._notify_command_handlers(self.poll_handlers, new_polls, 'poll') - def process_new_poll_answer(self, poll_answers): + def process_new_poll_answer(self, new_poll_answers): """ :meta private: """ - self._notify_command_handlers(self.poll_answer_handlers, poll_answers, 'poll_answer') + self._notify_command_handlers(self.poll_answer_handlers, new_poll_answers, 'poll_answer') - def process_new_my_chat_member(self, my_chat_members): + def process_new_my_chat_member(self, new_my_chat_members): """ :meta private: """ - self._notify_command_handlers(self.my_chat_member_handlers, my_chat_members, 'my_chat_member') + self._notify_command_handlers(self.my_chat_member_handlers, new_my_chat_members, 'my_chat_member') - def process_new_chat_member(self, chat_members): + def process_new_chat_member(self, new_chat_members): """ :meta private: """ - self._notify_command_handlers(self.chat_member_handlers, chat_members, 'chat_member') + self._notify_command_handlers(self.chat_member_handlers, new_chat_members, 'chat_member') - def process_new_chat_join_request(self, chat_join_request): + def process_new_chat_join_request(self, new_chat_join_request): """ :meta private: """ - self._notify_command_handlers(self.chat_join_request_handlers, chat_join_request, 'chat_join_request') + self._notify_command_handlers(self.chat_join_request_handlers, new_chat_join_request, 'chat_join_request') - def process_new_chat_boost(self, chat_boosts): + def process_new_chat_boost(self, new_chat_boosts): """ :meta private: """ - self._notify_command_handlers(self.chat_boost_handlers, chat_boosts, 'chat_boost') + self._notify_command_handlers(self.chat_boost_handlers, new_chat_boosts, 'chat_boost') - def process_new_removed_chat_boost(self, removed_chat_boosts): + def process_new_removed_chat_boost(self, new_removed_chat_boosts): """ :meta private: """ - self._notify_command_handlers(self.removed_chat_boost_handlers, removed_chat_boosts, 'removed_chat_boost') + self._notify_command_handlers(self.removed_chat_boost_handlers, new_removed_chat_boosts, 'removed_chat_boost') def process_middlewares(self, update): From 79cc12772fe8f9d6a2e3740e8ab31ad9462afefb Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 00:25:39 +0300 Subject: [PATCH 087/480] reply_to_message_id and allow_sending_without_reply deprecation reply_to_message_id and allow_sending_without_reply deprecation extended with more precise values processing --- telebot/__init__.py | 723 +++++++++++++++++++++++++++----------------- 1 file changed, 450 insertions(+), 273 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 6c872cda4..1cfc5a558 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1553,13 +1553,13 @@ def send_message( disable_web_page_preview: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - link_preview_options : Optional[types.ReplyParameters]=None) -> types.Message: + link_preview_options : Optional[types.LinkPreviewOptions]=None) -> types.Message: """ Use this method to send text messages. @@ -1590,10 +1590,10 @@ def send_message( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -1619,17 +1619,27 @@ def send_message( disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if disable_web_page_preview: # show a deprecation warning @@ -1698,9 +1708,8 @@ def copy_message( caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID: @@ -1732,10 +1741,10 @@ def copy_message( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -1758,17 +1767,27 @@ def copy_message( disable_notification = self.disable_notification if (disable_notification is None) else disable_notification parse_mode = self.parse_mode if (parse_mode is None) else parse_mode protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.MessageID.de_json( apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, @@ -1898,10 +1917,10 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], def send_dice( self, chat_id: Union[int, str], emoji: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -1920,20 +1939,20 @@ def send_dice( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` - :param timeout: Timeout in seconds for the request. - :type timeout: :obj:`int` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -1948,17 +1967,27 @@ def send_dice( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( apihelper.send_dice( @@ -1973,8 +2002,8 @@ def send_photo( caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, @@ -2008,10 +2037,10 @@ def send_photo( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions @@ -2037,17 +2066,27 @@ def send_photo( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( apihelper.send_photo( @@ -2060,14 +2099,14 @@ def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], caption: Optional[str]=None, duration: Optional[int]=None, performer: Optional[str]=None, title: Optional[str]=None, - reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, @@ -2101,9 +2140,6 @@ def send_audio( :param title: Track name :type title: :obj:`str` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param reply_markup: :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` @@ -2114,6 +2150,12 @@ def send_audio( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` + + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` @@ -2126,9 +2168,6 @@ def send_audio( :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -2147,17 +2186,27 @@ def send_audio( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumb is not None and thumbnail is None: thumbnail = thumb @@ -2173,13 +2222,13 @@ def send_audio( def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], caption: Optional[str]=None, duration: Optional[int]=None, - reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -2203,9 +2252,6 @@ def send_voice( :param duration: Duration of the voice message in seconds :type duration: :obj:`int` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -2217,15 +2263,18 @@ def send_voice( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` + + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -2240,17 +2289,27 @@ def send_voice( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( apihelper.send_voice( @@ -2261,15 +2320,15 @@ def send_voice( # TODO: Rewrite this method like in API. def send_document( self, chat_id: Union[int, str], document: Union[Any, str], - reply_to_message_id: Optional[int]=None, caption: Optional[str]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - allow_sending_without_reply: Optional[bool]=None, visible_file_name: Optional[str]=None, disable_content_type_detection: Optional[bool]=None, data: Optional[Union[Any, str]]=None, @@ -2288,9 +2347,6 @@ def send_document( String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data :type document: :obj:`str` or :class:`telebot.types.InputFile` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param caption: Document caption (may also be used when resending documents by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -2305,6 +2361,12 @@ def send_document( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` + + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` @@ -2314,9 +2376,6 @@ def send_document( :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param visible_file_name: allows to define file name that will be visible in the Telegram instead of original file name :type visible_file_name: :obj:`str` @@ -2344,17 +2403,27 @@ def send_document( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if data and (not document): # function typo miss compatibility @@ -2378,11 +2447,11 @@ def send_document( def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], - reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content:Optional[bool]=None, data: Union[Any, str]=None, message_thread_id: Optional[int]=None, @@ -2401,9 +2470,6 @@ def send_sticker( as a String for Telegram to get a .webp file from the Internet, or upload a new one using multipart/form-data. :type sticker: :obj:`str` or :class:`telebot.types.InputFile` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -2412,12 +2478,15 @@ def send_sticker( :param disable_notification: to disable the notification :type disable_notification: :obj:`bool` - :param timeout: Timeout in seconds for the request. - :type timeout: :obj:`int` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -2438,23 +2507,33 @@ def send_sticker( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if data and (not sticker): - # function typo miss compatibility - logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') - sticker = data + if allow_sending_without_reply is not None: + # show a deprecation warning + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - if allow_sending_without_reply or reply_to_message_id: + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + if data and (not sticker): + # function typo miss compatibility + logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') + sticker = data + return types.Message.de_json( apihelper.send_data( self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup, @@ -2474,8 +2553,8 @@ def send_video( supports_streaming: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, data: Optional[Union[Any, str]]=None, @@ -2524,10 +2603,10 @@ def send_video( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -2559,7 +2638,27 @@ def send_video( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + + if allow_sending_without_reply is not None: + # show a deprecation warning + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if data and (not video): # function typo miss compatibility @@ -2570,16 +2669,6 @@ def send_video( thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') - if allow_sending_without_reply or reply_to_message_id: - # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") - - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) - return types.Message.de_json( apihelper.send_video( self.token, chat_id, video, duration, caption, reply_markup, @@ -2597,8 +2686,8 @@ def send_animation( caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, @@ -2642,9 +2731,12 @@ def send_animation( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -2659,9 +2751,6 @@ def send_animation( :param caption_entities: List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param message_thread_id: Identifier of a message thread, in which the video will be sent :type message_thread_id: :obj:`int` @@ -2680,17 +2769,27 @@ def send_animation( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumbnail is None and thumb is not None: thumbnail = thumb @@ -2706,12 +2805,12 @@ def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], duration: Optional[int]=None, length: Optional[int]=None, - reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, @@ -2735,9 +2834,6 @@ def send_video_note( :param length: Video width and height, i.e. diameter of the video message :type length: :obj:`int` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -2746,6 +2842,12 @@ def send_video_note( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` + + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` @@ -2755,9 +2857,6 @@ def send_video_note( so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -2775,21 +2874,31 @@ def send_video_note( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if thumbnail is None and thumb is not None: - thumbnail = thumb - logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + if allow_sending_without_reply is not None: + # show a deprecation warning + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - if allow_sending_without_reply or reply_to_message_id: + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + + if thumbnail is None and thumb is not None: + thumbnail = thumb + logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') return types.Message.de_json( apihelper.send_video_note( @@ -2804,9 +2913,9 @@ def send_media_group( types.InputMediaPhoto, types.InputMediaVideo]], disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]: """ @@ -2827,15 +2936,15 @@ def send_media_group( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param message_thread_id: Identifier of a message thread, in which the media group will be sent :type message_thread_id: :obj:`int` @@ -2847,17 +2956,27 @@ def send_media_group( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = apihelper.send_media_group( self.token, chat_id, media, disable_notification, timeout, @@ -2869,14 +2988,14 @@ def send_location( self, chat_id: Union[int, str], latitude: float, longitude: float, live_period: Optional[int]=None, - reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, horizontal_accuracy: Optional[float]=None, heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -2897,9 +3016,6 @@ def send_location( :param live_period: Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400. :type live_period: :obj:`int` - :param reply_to_message_id: If the message is a reply, ID of the original message - :type reply_to_message_id: :obj:`int` - :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -2908,6 +3024,12 @@ def send_location( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :type reply_to_message_id: :obj:`int` + + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` @@ -2920,9 +3042,6 @@ def send_location( :param proximity_alert_radius: For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -2937,17 +3056,27 @@ def send_location( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( apihelper.send_location( @@ -3056,10 +3185,10 @@ def send_venue( foursquare_id: Optional[str]=None, foursquare_type: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, google_place_id: Optional[str]=None, google_place_type: Optional[str]=None, protect_content: Optional[bool]=None, @@ -3095,9 +3224,12 @@ def send_venue( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -3106,10 +3238,6 @@ def send_venue( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified - replied-to messages is not found. - :type allow_sending_without_reply: :obj:`bool` - :param google_place_id: Google Places identifier of the venue :type google_place_id: :obj:`str` @@ -3130,17 +3258,27 @@ def send_venue( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( apihelper.send_venue( @@ -3155,10 +3293,10 @@ def send_contact( first_name: str, last_name: Optional[str]=None, vcard: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ @@ -3184,9 +3322,12 @@ def send_contact( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` @@ -3195,10 +3336,6 @@ def send_contact( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified - replied-to messages is not found. - :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -3213,17 +3350,27 @@ def send_contact( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( apihelper.send_contact( @@ -4305,10 +4452,10 @@ def edit_message_reply_markup( def send_game( self, chat_id: Union[int, str], game_short_name: str, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -4326,18 +4473,18 @@ def send_game( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :obj:`InlineKeyboardMarkup` or :obj:`ReplyKeyboardMarkup` or :obj:`ReplyKeyboardRemove` or :obj:`ForceReply` :param timeout: Timeout in seconds for waiting for a response from the bot. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified replied-to messages is not found. - :type allow_sending_without_reply: :obj:`bool` - :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` @@ -4352,17 +4499,27 @@ def send_game( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = apihelper.send_game( self.token, chat_id, game_short_name, disable_notification, @@ -4457,11 +4614,11 @@ def send_invoice( send_email_to_provider: Optional[bool]=None, is_flexible: Optional[bool]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, provider_data: Optional[str]=None, timeout: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, protect_content: Optional[bool]=None, @@ -4537,9 +4694,12 @@ def send_invoice( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :type allow_sending_without_reply: :obj:`bool` + :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button :type reply_markup: :obj:`str` @@ -4551,9 +4711,6 @@ def send_invoice( :param timeout: Timeout of a request, defaults to None :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found - :type allow_sending_without_reply: :obj:`bool` - :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency :type max_tip_amount: :obj:`int` @@ -4576,17 +4733,27 @@ def send_invoice( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = apihelper.send_invoice( self.token, chat_id, title, description, invoice_payload, provider_token, @@ -4713,9 +4880,9 @@ def send_poll( close_date: Optional[Union[int, datetime]]=None, is_closed: Optional[bool]=None, disable_notification: Optional[bool]=False, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - allow_sending_without_reply: Optional[bool]=None, timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, @@ -4768,10 +4935,10 @@ def send_poll( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the poll allows multiple options to be voted simultaneously. + :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, @@ -4799,20 +4966,30 @@ def send_poll( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if isinstance(question, types.Poll): - raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") - - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_to_message_id: + # show a deprecation warning + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + + if isinstance(question, types.Poll): + raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode From 56fbcafa47beca89b78694ce83f2b959351bc072 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 00:39:06 +0300 Subject: [PATCH 088/480] disable_web_page_preview deprecation disable_web_page_preview deprecation extended with more precise values processing --- telebot/__init__.py | 47 ++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 1cfc5a558..80adb2154 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1550,7 +1550,7 @@ def send_message( self, chat_id: Union[int, str], text: str, parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, - disable_web_page_preview: Optional[bool]=None, + disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility @@ -1581,7 +1581,7 @@ def send_message( :param entities: List of special entities that appear in message text, which can be specified instead of parse_mode :type entities: Array of :class:`telebot.types.MessageEntity` - :param disable_web_page_preview: Disables link previews for links in this message + :param disable_web_page_preview: deprecated. Disables link previews for links in this message :type disable_web_page_preview: :obj:`bool` :param disable_notification: Sends the message silently. Users will receive a notification with no sound. @@ -1616,7 +1616,6 @@ def send_message( :rtype: :class:`telebot.types.Message` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode - disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content @@ -1641,14 +1640,21 @@ def send_message( if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply - if disable_web_page_preview: + if disable_web_page_preview is not None: # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") - # create a LinkPreviewOptions object - link_preview_options = types.LinkPreviewOptions( - disable_web_page_preview=disable_web_page_preview - ) + if link_preview_options: + # show a conflict warning + logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") + else: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + disable_web_page_preview=disable_web_page_preview + ) + + if link_preview_options and (link_preview_options.disable_web_page_preview is None): + link_preview_options.disable_web_page_preview = self.disable_web_page_preview return types.Message.de_json( apihelper.send_message( @@ -4327,7 +4333,7 @@ def edit_message_text( inline_message_id: Optional[str]=None, parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, - disable_web_page_preview: Optional[bool]=None, + disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[types.InlineKeyboardMarkup]=None, link_preview_options : Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]: """ @@ -4353,7 +4359,7 @@ def edit_message_text( :param entities: List of special entities that appear in the message text, which can be specified instead of parse_mode :type entities: List of :obj:`telebot.types.MessageEntity` - :param disable_web_page_preview: Disables link previews for links in this message + :param disable_web_page_preview: deprecated. Disables link previews for links in this message :type disable_web_page_preview: :obj:`bool` :param reply_markup: A JSON-serialized object for an inline keyboard. @@ -4366,17 +4372,22 @@ def edit_message_text( :rtype: :obj:`types.Message` or :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode - disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview - - if disable_web_page_preview: + + if disable_web_page_preview is not None: # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") - # create a LinkPreviewOptions object - link_preview_options = types.LinkPreviewOptions( - disable_web_page_preview=disable_web_page_preview - ) - + if link_preview_options: + # show a conflict warning + logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") + else: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + disable_web_page_preview=disable_web_page_preview + ) + + if link_preview_options and (link_preview_options.disable_web_page_preview is None): + link_preview_options.disable_web_page_preview = self.disable_web_page_preview result = apihelper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, entities, reply_markup, link_preview_options) From 778a02c45b3291dca447d1cecc395d0c9de45b69 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 00:45:46 +0300 Subject: [PATCH 089/480] Fix forward_messages return value --- telebot/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 80adb2154..8b0a5d1fc 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1879,8 +1879,8 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - return types.MessageID.de_json( - apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id)) + return [types.MessageID.de_json(message_id) for message_id in + apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id))] def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, From 0af7f6f56c19271f35b89e3f9de9be35daebd40c Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 00:47:45 +0300 Subject: [PATCH 090/480] Fix forward_messages return value in Async --- telebot/async_telebot.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 658443124..685f725c7 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2932,8 +2932,7 @@ async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[s disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id) - return types.MessageID.de_json( - result) + return [types.MessageID.de_json(message_id) for message_id in result] async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, @@ -2969,8 +2968,7 @@ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, protect_content = self.protect_content if protect_content is None else protect_content result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id, remove_caption) - return [types.MessageID.de_json(message_id) for message_id in - result] + return [types.MessageID.de_json(message_id) for message_id in result] async def send_dice( self, chat_id: Union[int, str], From 0ace17bdb5928327d493cf0045165b390b1ce6f5 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 00:48:34 +0300 Subject: [PATCH 091/480] Fix the fix forward_messages return value --- telebot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 8b0a5d1fc..5b2598d18 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1880,7 +1880,7 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in protect_content = self.protect_content if (protect_content is None) else protect_content return [types.MessageID.de_json(message_id) for message_id in - apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id))] + apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id)] def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, From 578d6a37d23a4b8d8454416b7a022f98465245bf Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 01:23:41 +0300 Subject: [PATCH 092/480] Fix message_reaction_x_handler description --- telebot/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 5b2598d18..3cbc6d7b1 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6830,7 +6830,7 @@ def register_edited_channel_post_handler(self, callback: Callable, content_types def message_reaction_handler(self, func=None, **kwargs): """ Handles new incoming message reaction. - As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionUpdated` object. :param func: Function executed as a filter :type func: :obj:`function` @@ -6881,7 +6881,7 @@ def register_message_reaction_handler(self, callback: Callable, func: Callable=N def message_reaction_count_handler(self, func=None, **kwargs): """ Handles new incoming message reaction count. - As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionCountUpdated` object. :param func: Function executed as a filter :type func: :obj:`function` From 4359f4f14da43aabe8c54bc6d5fc3739aa9710ca Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 01:23:51 +0300 Subject: [PATCH 093/480] Fix message_reaction_x_handler description for Async --- telebot/async_telebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 685f725c7..3e8b305a3 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -1400,7 +1400,7 @@ def register_edited_channel_post_handler(self, callback: Callable[[Any], Awaitab def message_reaction_handler(self, func=None, **kwargs): """ Handles new incoming message reaction. - As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionUpdated` object. :param func: Function executed as a filter :type func: :obj:`function` @@ -1452,7 +1452,7 @@ def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable] def message_reaction_count_handler(self, func=None, **kwargs): """ Handles new incoming message reaction count. - As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + As a parameter to the decorator function, it passes :class:`telebot.types.MessageReactionCountUpdated` object. :param func: Function executed as a filter :type func: :obj:`function` From 9831ae2cd414fc3ff9bf8eeeef1c0bcea0af4b47 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 13:33:37 +0300 Subject: [PATCH 094/480] Fix and align reply_parameters --- telebot/apihelper.py | 59 +++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 5f8702533..c69ce3c56 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -447,9 +447,6 @@ def send_dice( payload['emoji'] = emoji if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: @@ -458,6 +455,9 @@ def send_dice( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -509,15 +509,15 @@ def send_media_group( payload = {'chat_id': chat_id, 'media': media_json} if disable_notification is not None: payload['disable_notification'] = disable_notification - if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if timeout: payload['timeout'] = timeout if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id is not None: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request( token, method_url, params=payload, method='post' if files else 'get', @@ -625,6 +625,9 @@ def send_venue( payload['protect_content'] = protect_content if message_thread_id is not None: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -750,9 +753,6 @@ def send_animation( payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if width: @@ -763,6 +763,9 @@ def send_animation( payload['message_thread_id'] = message_thread_id if has_spoiler is not None: payload['has_spoiler'] = has_spoiler + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -830,13 +833,13 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark files = {'thumbnail': thumbnail} else: payload['thumbnail'] = thumbnail - if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -883,7 +886,6 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non if reply_parameters is not None: # to json payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) - return _make_request(token, method_url, params=payload, files=files, method='post') @@ -921,9 +923,6 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['thumbnail'] = thumbnail if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) - if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if method_url == 'sendDocument' and disable_content_type_detection is not None: @@ -932,6 +931,9 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['message_thread_id'] = message_thread_id if emoji: payload['emoji'] = emoji + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1390,13 +1392,13 @@ def send_game( payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout - if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if protect_content is not None: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) @@ -1786,9 +1788,8 @@ def create_invoice_link(token, title, description, payload, provider_token, def send_poll( token, chat_id, question, options, - is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, - explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, - disable_notification=False, + is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, + explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None): method_url = r'sendPoll' payload = { @@ -1817,11 +1818,8 @@ def send_poll( payload['close_date'] = close_date if is_closed is not None: payload['is_closed'] = is_closed - if disable_notification: payload['disable_notification'] = disable_notification - if reply_parameters is not None: - payload['reply_parameters'] = reply_parameters.to_json() if reply_markup is not None: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: @@ -1833,6 +1831,9 @@ def send_poll( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if reply_parameters is not None: + # to json + payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) return _make_request(token, method_url, params=payload) def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None): @@ -1931,9 +1932,7 @@ def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notifica payload['message_thread_id'] = message_thread_id if protect_content is not None: payload['protect_content'] = protect_content - - result = _make_request(token, method_url, params=payload) - return result + return _make_request(token, method_url, params=payload) def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, message_thread_id=None, protect_content=None, remove_caption=None): @@ -1951,9 +1950,7 @@ def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notificatio payload['protect_content'] = protect_content if remove_caption is not None: payload['remove_caption'] = remove_caption - - result = _make_request(token, method_url, params=payload) - return result + return _make_request(token, method_url, params=payload) def _convert_list_json_serializable(results): From 71f53d3b0e5bca8beaa088bc26beda7193c62e7d Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 15:24:20 +0300 Subject: [PATCH 095/480] Fix minor bugs in types.py --- telebot/types.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index feb16094a..ae3b4162b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1272,14 +1272,10 @@ def de_json(cls, json_string): content_type = 'story' if 'external_reply' in obj: opts['external_reply'] = ExternalReplyInfo.de_json(obj['external_reply']) - content_type = 'text' # @Badiboy not sure about content_types in here, please check if 'quote' in obj: opts['quote'] = TextQuote.de_json(obj['quote']) - content_type = 'text' # Here too, check the content types - if 'link_preview_options' in obj: opts['link_preview_options'] = LinkPreviewOptions.de_json(obj['link_preview_options']) - if 'giveaway_created' in obj: opts['giveaway_created'] = GiveawayCreated.de_json(obj['giveaway_created']) content_type = 'giveaway_created' @@ -1396,7 +1392,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.story: Optional[Story] = None self.external_reply: Optional[ExternalReplyInfo] = None self.quote: Optional[TextQuote] = None - self.LinkPreviewOptions: Optional[LinkPreviewOptions] = None + self.link_preview_options: Optional[LinkPreviewOptions] = None self.giveaway_created: Optional[GiveawayCreated] = None self.giveaway: Optional[Giveaway] = None self.giveaway_winners: Optional[GiveawayWinners] = None @@ -3713,7 +3709,7 @@ class InputTextMessageContent(Dictionaryable): parse_mode :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param disable_web_page_preview: Optional. Disables link previews for links in the sent message + :param disable_web_page_preview: Optional, deprecated. Disables link previews for links in the sent message :type disable_web_page_preview: :obj:`bool` :return: Instance of the class @@ -3724,11 +3720,13 @@ def __init__(self, message_text, parse_mode=None, entities=None, disable_web_pag self.parse_mode: str = parse_mode self.entities: List[MessageEntity] = entities link_preview_options: LinkPreviewOptions = link_preview_options - if disable_web_page_preview is not None and link_preview_options is None: - # deprecated - self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(disable_web_page_preview) + if disable_web_page_preview is not None: + logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") - + if link_preview_options: + logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") + else: + self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(disable_web_page_preview) def to_dict(self): json_dict = {'message_text': self.message_text} @@ -9215,4 +9213,4 @@ def de_json(cls, json_string): obj['chat'] = Chat.de_json(obj.get('chat')) return cls(**obj) - \ No newline at end of file + From b96084f1f72346423aae3f3ab2671a05c4454c10 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 15:53:17 +0300 Subject: [PATCH 096/480] reply_parameters => to_json --- telebot/apihelper.py | 51 +++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index c69ce3c56..d307e9bae 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -260,8 +260,7 @@ def send_message( if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, method='post') @@ -426,8 +425,7 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m if disable_notification is not None: payload['disable_notification'] = disable_notification if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() if timeout: payload['timeout'] = timeout if protect_content is not None: @@ -456,8 +454,7 @@ def send_dice( if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -495,8 +492,7 @@ def send_photo( if has_spoiler is not None: payload['has_spoiler'] = has_spoiler if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -516,8 +512,7 @@ def send_media_group( if message_thread_id is not None: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request( token, method_url, params=payload, method='post' if files else 'get', @@ -552,8 +547,7 @@ def send_location( if message_thread_id is not None: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -626,8 +620,7 @@ def send_venue( if message_thread_id is not None: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -652,8 +645,7 @@ def send_contact( if message_thread_id is not None: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -714,8 +706,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N if has_spoiler is not None: payload['has_spoiler'] = has_spoiler if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -764,8 +755,7 @@ def send_animation( if has_spoiler is not None: payload['has_spoiler'] = has_spoiler if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -798,8 +788,7 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -838,8 +827,7 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -884,8 +872,7 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -932,8 +919,7 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non if emoji: payload['emoji'] = emoji if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1397,8 +1383,7 @@ def send_game( if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -1545,8 +1530,7 @@ def send_invoice( if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -1832,8 +1816,7 @@ def send_poll( if message_thread_id: payload['message_thread_id'] = message_thread_id if reply_parameters is not None: - # to json - payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + payload['reply_parameters'] = reply_parameters.to_json() return _make_request(token, method_url, params=payload) def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None): From 0c9bdfb981177859e99c98fa96dfbf96cf319b05 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 16:18:56 +0300 Subject: [PATCH 097/480] Fix classes loading in types.py --- telebot/types.py | 260 +++++++++++++++++++---------------------------- 1 file changed, 104 insertions(+), 156 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index ae3b4162b..5b8c42536 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1148,7 +1148,7 @@ def de_json(cls, json_string): if 'caption' in obj: opts['caption'] = obj['caption'] if 'contact' in obj: - opts['contact'] = Contact.de_json(json.dumps(obj['contact'])) + opts['contact'] = Contact.de_json(obj['contact']) content_type = 'contact' if 'location' in obj: opts['location'] = Location.de_json(obj['location']) @@ -7932,7 +7932,6 @@ def __init__(self, text: str, web_app: Optional[WebAppInfo]=None, start_paramete self.web_app: Optional[WebAppInfo] = web_app self.start_parameter: Optional[str] = start_parameter - def to_dict(self) -> dict: json_dict = { 'text': self.text @@ -7965,6 +7964,7 @@ def de_json(cls, json_string): def __init__(self) -> None: pass + # base class class ReactionType(JsonDeserializable, Dictionaryable, JsonSerializable): """ @@ -7999,7 +7999,6 @@ def to_dict(self) -> dict: json_dict = { 'type': self.type } - return json_dict def to_json(self) -> str: @@ -8029,11 +8028,8 @@ def __init__(self, emoji: str) -> None: def to_dict(self) -> dict: json_dict = super().to_dict() json_dict['emoji'] = self.emoji + return json_dict - return json_dict - - - class ReactionTypeCustomEmoji(ReactionType): """ @@ -8058,11 +8054,8 @@ def __init__(self, custom_emoji: str) -> None: def to_dict(self) -> dict: json_dict = super().to_dict() json_dict['custom_emoji'] = self.custom_emoji - return json_dict - - - + class MessageReactionUpdated(JsonDeserializable): """ @@ -8101,15 +8094,13 @@ def de_json(cls, json_string): return None obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) if 'user' in obj: obj['user'] = User.de_json(obj['user']) if 'actor_chat' in obj: obj['actor_chat'] = Chat.de_json(obj['actor_chat']) obj['old_reaction'] = [ReactionType.de_json(reaction) for reaction in obj['old_reaction']] obj['new_reaction'] = [ReactionType.de_json(reaction) for reaction in obj['new_reaction']] - if 'chat' in obj: - obj['chat'] = Chat.de_json(obj['chat']) - return cls(**obj) def __init__(self, chat: Chat, message_id: int, date: int, old_reaction: List[ReactionType], new_reaction: List[ReactionType], @@ -8151,10 +8142,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - obj['reactions'] = [ReactionCount.de_json(reaction) for reaction in obj['reactions']] obj['chat'] = Chat.de_json(obj['chat']) - + obj['reactions'] = [ReactionCount.de_json(reaction) for reaction in obj['reactions']] return cls(**obj) def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[ReactionCount]) -> None: @@ -8185,9 +8174,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['type'] = ReactionType.de_json(obj['type']) - return cls(**obj) def __init__(self, type: ReactionType, total_count: int) -> None: @@ -8195,7 +8182,6 @@ def __init__(self, type: ReactionType, total_count: int) -> None: self.total_count: int = total_count - class ExternalReplyInfo(JsonDeserializable): """ This object contains information about a message that is being replied to, @@ -8280,23 +8266,14 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + origin = MessageOrigin.de_json(obj['origin']) + if 'chat' in obj: + chat = Chat.de_json(obj['chat']) + if 'link_preview_options' in obj: + link_preview_options = LinkPreviewOptions.de_json(obj['link_preview_options']) - origin = obj.get('origin') - if origin is not None: - origin = MessageOrigin.de_json(origin) + #todo: update data processing to common way - chat = obj.get('chat') - if chat is not None: - chat = Chat.de_json(chat) - - message_id = obj.get('message_id') - if message_id is not None: - message_id = int(message_id) - - link_preview_options = obj.get('link_preview_options') - if link_preview_options is not None: - link_preview_options = LinkPreviewOptions.de_json(link_preview_options) - animation = obj.get('animation') if animation is not None: animation = Animation.de_json(animation) @@ -8414,6 +8391,7 @@ def __init__(self, origin: MessageOrigin, chat: Optional[Chat]=None, message_id: self.poll: Optional[Poll] = poll self.venue: Optional[Venue] = venue + class MessageOrigin(JsonDeserializable): """ This object describes the origin of a message. @@ -8450,16 +8428,16 @@ def de_json(cls, json_string): message_type = obj.get('type') if message_type == 'user': - sender_user = User.de_json(obj.get('sender_user')) - return MessageOriginUser(date=obj.get('date'), sender_user=sender_user) + sender_user = User.de_json(obj['sender_user']) + return MessageOriginUser(date=obj['date'], sender_user=sender_user) elif message_type == 'hidden_user': - return MessageOriginHiddenUser(date=obj.get('date'), sender_user_name=obj.get('sender_user_name')) + return MessageOriginHiddenUser(date=obj['date'], sender_user_name=obj['sender_user_name']) elif message_type == 'chat': - sender_chat = Chat.de_json(obj.get('sender_chat')) - return MessageOriginChat(date=obj.get('date'), sender_chat=sender_chat, author_signature=obj.get('author_signature')) + sender_chat = Chat.de_json(obj['sender_chat']) + return MessageOriginChat(date=obj['date'], sender_chat=sender_chat, author_signature=obj.get('author_signature')) elif message_type == 'channel': - chat = Chat.de_json(obj.get('chat')) - return MessageOriginChannel(date=obj.get('date'), chat=chat, message_id=obj.get('message_id'), author_signature=obj.get('author_signature')) + chat = Chat.de_json(obj['chat']) + return MessageOriginChannel(date=obj['date'], chat=chat, message_id=obj['message_id'], author_signature=obj.get('author_signature')) def __init__(self, type: str, date: int) -> None: self.type: str = type @@ -8474,9 +8452,9 @@ class MessageOriginUser(MessageOrigin): :type sender_user: :class:`User` """ - def __init__(self, date: int, sender_user: Optional[User] = None) -> None: + def __init__(self, date: int, sender_user: User) -> None: super().__init__('user', date) - self.sender_user: Optional[User] = sender_user + self.sender_user: User = sender_user class MessageOriginHiddenUser(MessageOrigin): @@ -8487,9 +8465,9 @@ class MessageOriginHiddenUser(MessageOrigin): :type sender_user_name: :obj:`str` """ - def __init__(self, date: int, sender_user_name: Optional[str] = None) -> None: + def __init__(self, date: int, sender_user_name: str) -> None: super().__init__('hidden_user', date) - self.sender_user_name: Optional[str] = sender_user_name + self.sender_user_name: str = sender_user_name class MessageOriginChat(MessageOrigin): @@ -8503,9 +8481,9 @@ class MessageOriginChat(MessageOrigin): :type author_signature: :obj:`str` """ - def __init__(self, date: int, sender_chat: Optional[Chat] = None, author_signature: Optional[str] = None) -> None: + def __init__(self, date: int, sender_chat: Chat, author_signature: Optional[str] = None) -> None: super().__init__('chat', date) - self.sender_chat: Optional[Chat] = sender_chat + self.sender_chat: Chat = sender_chat self.author_signature: Optional[str] = author_signature @@ -8523,10 +8501,10 @@ class MessageOriginChannel(MessageOrigin): :type author_signature: :obj:`str` """ - def __init__(self, date: int, chat: Optional[Chat] = None, message_id: Optional[int] = None, author_signature: Optional[str] = None) -> None: + def __init__(self, date: int, chat: Chat, message_id: int, author_signature: Optional[str] = None) -> None: super().__init__('channel', date) - self.chat: Optional[Chat] = chat - self.message_id: Optional[int] = message_id + self.chat: Chat = chat + self.message_id: int = message_id self.author_signature: Optional[str] = author_signature @@ -8560,7 +8538,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - + #todo: adopt to common way return cls(is_disabled=obj.get('is_disabled'), url=obj.get('url'), prefer_small_media=obj.get('prefer_small_media'), prefer_large_media=obj.get('prefer_large_media'), show_above_text=obj.get('show_above_text')) @@ -8632,10 +8610,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - chats = [Chat.de_json(chat) for chat in obj.get('chats', [])] - - return cls(**obj, chats=chats) + self.chats = [Chat.de_json(chat) for chat in obj['chats']] + return cls(**obj) def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: int, only_new_members: Optional[bool] = None, has_public_winners: Optional[bool] = None, @@ -8647,8 +8623,9 @@ def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: self.only_new_members: Optional[bool] = only_new_members self.has_public_winners: Optional[bool] = has_public_winners self.prize_description: Optional[str] = prize_description - self.country_codes: Optional[List[str]] = country_codes or [] + self.country_codes: Optional[List[str]] = country_codes self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count + class GiveawayWinners(JsonDeserializable): """ @@ -8698,10 +8675,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - obj['chat'] = Chat.de_json(obj.get('chat')) - obj['winners'] = [User.de_json(user) for user in obj.get('winners', [])] - + obj['chat'] = Chat.de_json(obj['chat']) + obj['winners'] = [User.de_json(user) for user in obj['winners']] return cls(**obj) def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: int, winner_count: int, @@ -8720,6 +8695,7 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: self.only_new_members: Optional[bool] = only_new_members self.was_refunded: Optional[bool] = was_refunded self.prize_description: Optional[str] = prize_description + class GiveawayCompleted(JsonDeserializable): """ @@ -8745,9 +8721,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - obj['giveaway_message'] = Message.de_json(obj.get('giveaway_message')) - + if 'giveaway_message' in obj: + obj['giveaway_message'] = Message.de_json(obj['giveaway_message']) return cls(**obj) def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = None, @@ -8755,11 +8730,13 @@ def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = Non self.winner_count: int = winner_count self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count self.giveaway_message: Optional[Message] = giveaway_message + class GiveawayCreated(JsonDeserializable): """ This object represents a service message about the creation of a scheduled giveaway. Currently holds no information. """ + class TextQuote(JsonDeserializable): """ @@ -8788,9 +8765,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['entities'] = [MessageEntity.de_json(entity) for entity in obj.get('entities', [])] - return cls(**obj) def __init__(self, text: str, entities: Optional[List[MessageEntity]] = None, @@ -8800,6 +8775,7 @@ def __init__(self, text: str, entities: Optional[List[MessageEntity]] = None, self.position: Optional[int] = position self.is_manual: Optional[bool] = is_manual + class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable): """ Describes reply parameters for the message that is being sent. @@ -8836,11 +8812,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj.get('quote_entities', [])] - - return cls(**obj) - + return cls(**obj) def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, allow_sending_without_reply: Optional[bool] = None, quote: Optional[str] = None, @@ -8854,12 +8827,10 @@ def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, self.quote_entities: Optional[List[MessageEntity]] = quote_entities self.quote_position: Optional[int] = quote_position - def to_dict(self) -> dict: json_dict = { 'message_id': self.message_id } - if self.chat_id is not None: json_dict['chat_id'] = self.chat_id if self.allow_sending_without_reply is not None: @@ -8872,11 +8843,11 @@ def to_dict(self) -> dict: json_dict['quote_entities'] = [entity.to_dict() for entity in self.quote_entities] if self.quote_position is not None: json_dict['quote_position'] = self.quote_position - return json_dict def to_json(self) -> str: return json.dumps(self.to_dict()) + class UsersShared(JsonDeserializable): """ @@ -8900,16 +8871,16 @@ class UsersShared(JsonDeserializable): :rtype: :class:`UsersShared` """ - def __init__(self, request_id, user_ids): - self.request_id = request_id - self.user_ids = user_ids - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) + + def __init__(self, request_id, user_ids): + self.request_id = request_id + self.user_ids = user_ids class ChatBoostUpdated(JsonDeserializable): @@ -8928,29 +8899,19 @@ class ChatBoostUpdated(JsonDeserializable): :rtype: :class:`ChatBoostUpdated` """ - def __init__(self, chat, boost): - self.chat = chat - self.boost = boost - @classmethod def de_json(cls, json_string): if json_string is None: return None - obj = cls.check_json(json_string) - - obj['chat'] = Chat.de_json(obj.get('chat')) - obj['boost'] = ChatBoost.de_json(obj.get('boost')) - + obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) + obj['boost'] = ChatBoost.de_json(obj['boost']) return cls(**obj) - -# ChatBoostRemoved -# This object represents a boost removed from a chat. - -# Field Type Description -# chat Chat Chat which was boosted -# boost_id String Unique identifier of the boost -# remove_date Integer Point in time (Unix timestamp) when the boost was removed -# source ChatBoostSource Source of the removed boost + + def __init__(self, chat, boost): + self.chat = chat + self.boost = boost + class ChatBoostRemoved(JsonDeserializable): """ @@ -8974,22 +8935,21 @@ class ChatBoostRemoved(JsonDeserializable): :rtype: :class:`ChatBoostRemoved` """ - def __init__(self, chat, boost_id, remove_date, source): - self.chat = chat - self.boost_id = boost_id - self.remove_date = remove_date - self.source = source - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) + obj['source'] = ChatBoostSource.de_json(obj['source']) + return cls(**obj) - obj['chat'] = Chat.de_json(obj.get('chat')) - obj['source'] = ChatBoostSource.de_json(obj.get('source')) + def __init__(self, chat, boost_id, remove_date, source): + self.chat = chat + self.boost_id = boost_id + self.remove_date = remove_date + self.source = source - return cls(**obj) class ChatBoostSource(JsonDeserializable): """ @@ -9004,14 +8964,14 @@ class ChatBoostSource(JsonDeserializable): :rtype: :class:`ChatBoostSource` """ - def __init__(self, source): - self.source = source - @classmethod def de_json(cls, json_string): if json_string is None: return None return cls(**cls.check_json(json_string)) + + def __init__(self, source): + self.source = source class ChatBoostSourcePremium(ChatBoostSource): @@ -9030,17 +8990,18 @@ class ChatBoostSourcePremium(ChatBoostSource): :rtype: :class:`ChatBoostSourcePremium` """ - def __init__(self, user): - super().__init__('premium') - self.user = user - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - user = User.de_json(json.dumps(obj['user'])) + user = User.de_json(obj['user']) return cls(user) + + def __init__(self, user): + super().__init__('premium') + self.user = user + class ChatBoostSourceGiftCode(ChatBoostSource): """ @@ -9058,17 +9019,18 @@ class ChatBoostSourceGiftCode(ChatBoostSource): :rtype: :class:`ChatBoostSourceGiftCode` """ - def __init__(self, user): - super().__init__('gift_code') - self.user = user - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - user = User.de_json(json.dumps(obj['user'])) + user = User.de_json(obj['user']) return cls(user) + + def __init__(self, user): + super().__init__('gift_code') + self.user = user + class ChatBoostSourceGiveaway(ChatBoostSource): """ @@ -9092,29 +9054,21 @@ class ChatBoostSourceGiveaway(ChatBoostSource): :rtype: :class:`ChatBoostSourceGiveaway` """ - def __init__(self, giveaway_message_id, user=None, is_unclaimed=None): - super().__init__('giveaway') - self.giveaway_message_id = giveaway_message_id - self.user = user - self.is_unclaimed = is_unclaimed - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - user = User.de_json(json.dumps(obj['user'])) if 'user' in obj else None + user = User.de_json(obj['user']) if 'user' in obj else None return cls(obj['giveaway_message_id'], user, obj.get('is_unclaimed')) -#ChatBoost -# This object contains information about a chat boost. + def __init__(self, giveaway_message_id, user=None, is_unclaimed=None): + super().__init__('giveaway') + self.giveaway_message_id = giveaway_message_id + self.user = user + self.is_unclaimed = is_unclaimed + -# Field Type Description -# boost_id String Unique identifier of the boost -# add_date Integer Point in time (Unix timestamp) when the chat was boosted -# expiration_date Integer Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium subscription is prolonged -# source ChatBoostSource Source of the added boost - class ChatBoost(JsonDeserializable): """ This object contains information about a chat boost. @@ -9137,22 +9091,21 @@ class ChatBoost(JsonDeserializable): :rtype: :class:`ChatBoost` """ - def __init__(self, boost_id, add_date, expiration_date, source): - self.boost_id = boost_id - self.add_date = add_date - self.expiration_date = expiration_date - self.source: ChatBoostSource = source - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - obj['source'] = ChatBoostSource.de_json(json.dumps(obj['source'])) - + obj['source'] = ChatBoostSource.de_json(obj['source']) return cls(**obj) + def __init__(self, boost_id, add_date, expiration_date, source): + self.boost_id = boost_id + self.add_date = add_date + self.expiration_date = expiration_date + self.source: ChatBoostSource = source + + class UserChatBoosts(JsonDeserializable): """ This object represents a list of boosts added to a chat by a user. @@ -9166,18 +9119,16 @@ class UserChatBoosts(JsonDeserializable): :rtype: :class:`UserChatBoosts` """ - def __init__(self, boosts): - self.boosts: ChatBoost = boosts - @classmethod def de_json(cls, json_string): if json_string is None: return None - obj = cls.check_json(json_string) - obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj.get('boosts', [])] - + obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj['boosts']] return cls(**obj) + + def __init__(self, boosts): + self.boosts: ChatBoost = boosts class InaccessibleMessage(JsonDeserializable): @@ -9199,18 +9150,15 @@ class InaccessibleMessage(JsonDeserializable): :rtype: :class:`InaccessibleMessage` """ - def __init__(self, chat, message_id, date): - self.chat = chat - self.message_id = message_id - self.date = date - @classmethod def de_json(cls, json_string): if json_string is None: return None - obj = cls.check_json(json_string) - obj['chat'] = Chat.de_json(obj.get('chat')) - + obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) - + + def __init__(self, chat, message_id, date): + self.chat = chat + self.message_id = message_id + self.date = date From d0c3a7de0dfdc79c5cc708ae717cb459aa017410 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 16:47:53 +0300 Subject: [PATCH 098/480] Types: fix de_json of new classes --- telebot/types.py | 182 ++++++++++++++++++----------------------------- 1 file changed, 69 insertions(+), 113 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 5b8c42536..6f88621d1 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1360,7 +1360,6 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.venue: Optional[Venue] = None self.animation: Optional[Animation] = None self.dice: Optional[Dice] = None - self.new_chat_member: Optional[User] = None # Deprecated since Bot API 3.0. Not processed anymore self.new_chat_members: Optional[List[User]] = None self.left_chat_member: Optional[User] = None self.new_chat_title: Optional[str] = None @@ -1399,7 +1398,6 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.giveaway_completed: Optional[GiveawayCompleted] = None self.forward_origin: Optional[MessageOrigin] = None - for key in options: setattr(self, key, options[key]) self.json = json_string @@ -1514,6 +1512,11 @@ def html_caption(self): """ return self.__html_text(self.caption, self.caption_entities) + @property + def new_chat_member(self): + logger.warning('The parameter "new_chat_member" is deprecated, use "new_chat_members" instead') + return None + class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): """ @@ -8266,108 +8269,61 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - origin = MessageOrigin.de_json(obj['origin']) + obj['origin'] = MessageOrigin.de_json(obj['origin']) if 'chat' in obj: - chat = Chat.de_json(obj['chat']) + obj['chat'] = Chat.de_json(obj['chat']) if 'link_preview_options' in obj: - link_preview_options = LinkPreviewOptions.de_json(obj['link_preview_options']) + obj['link_preview_options'] = LinkPreviewOptions.de_json(obj['link_preview_options']) + if 'animation' in obj: + obj['animation'] = Animation.de_json(obj['animation']) + if 'audio' in obj: + obj['audio'] = Audio.de_json(obj['audio']) + if 'document' in obj: + obj['document'] = Document.de_json(obj['document']) + if 'photo' in obj: + obj['photo'] = Message.parse_photo(obj['photo']) + if 'sticker' in obj: + obj['sticker'] = Sticker.de_json(obj['sticker']) + if 'story' in obj: + obj['story'] = Story.de_json(obj['story']) + if 'video' in obj: + obj['video'] = Video.de_json(obj['video']) + if 'video_note' in obj: + obj['video_note'] = VideoNote.de_json(obj['video_note']) + if 'voice' in obj: + obj['voice'] = Voice.de_json(obj['voice']) + if 'contact' in obj: + obj['contact'] = Contact.de_json(obj['contact']) + if 'dice' in obj: + obj['dice'] = Dice.de_json(obj['dice']) + if 'game' in obj: + obj['game'] = Game.de_json(obj['game']) + if 'giveaway' in obj: + obj['giveaway'] = Giveaway.de_json(obj['giveaway']) + if 'giveaway_winners' in obj: + obj['giveaway_winners'] = GiveawayWinners.de_json(obj['giveaway_winners']) + if 'invoice' in obj: + obj['invoice'] = Invoice.de_json(obj['invoice']) + if 'location' in obj: + obj['location'] = Location.de_json(obj['location']) + if 'poll' in obj: + obj['poll'] = Poll.de_json(obj['poll']) + if 'venue' in obj: + obj['venue'] = Venue.de_json(obj['venue']) + return cls(**obj) - #todo: update data processing to common way - - animation = obj.get('animation') - if animation is not None: - animation = Animation.de_json(animation) - - audio = obj.get('audio') - if audio is not None: - audio = Audio.de_json(audio) - - document = obj.get('document') - if document is not None: - document = Document.de_json(document) - - photo = obj.get('photo') - if photo is not None: - photo = [PhotoSize.de_json(photo[i]) for i in range(len(photo))] - - sticker = obj.get('sticker') - if sticker is not None: - sticker = Sticker.de_json(sticker) - - story = obj.get('story') - if story is not None: - story = Story.de_json(story) - - video = obj.get('video') - if video is not None: - video = Video.de_json(video) - - video_note = obj.get('video_note') - if video_note is not None: - video_note = VideoNote.de_json(video_note) - - voice = obj.get('voice') - if voice is not None: - voice = Voice.de_json(voice) - - has_media_spoiler = obj.get('has_media_spoiler') - if has_media_spoiler is not None: - has_media_spoiler = bool(has_media_spoiler) - - contact = obj.get('contact') - if contact is not None: - contact = Contact.de_json(contact) - - dice = obj.get('dice') - if dice is not None: - dice = Dice.de_json(dice) - - game = obj.get('game') - if game is not None: - game = Game.de_json(game) - - giveaway = obj.get('giveaway') - if giveaway is not None: - giveaway = Giveaway.de_json(giveaway) - - giveaway_winners = obj.get('giveaway_winners') - if giveaway_winners is not None: - giveaway_winners = GiveawayWinners.de_json(giveaway_winners) - - invoice = obj.get('invoice') - if invoice is not None: - invoice = Invoice.de_json(invoice) - - location = obj.get('location') - if location is not None: - location = Location.de_json(location) - - poll = obj.get('poll') - if poll is not None: - poll = Poll.de_json(poll) - - venue = obj.get('venue') - if venue is not None: - venue = Venue.de_json(venue) - - return cls(origin=origin, chat=chat, message_id=message_id, link_preview_options=link_preview_options, - animation=animation, audio=audio, document=document, photo=photo, sticker=sticker, story=story, - video=video, video_note=video_note, voice=voice, has_media_spoiler=has_media_spoiler, - contact=contact, dice=dice, game=game, giveaway=giveaway, giveaway_winners=giveaway_winners, - invoice=invoice, location=location, poll=poll, venue=venue) - - def __init__(self, origin: MessageOrigin, chat: Optional[Chat]=None, message_id: Optional[int]=None, - link_preview_options: Optional[LinkPreviewOptions]=None, animation: Optional[Animation]=None, - audio: Optional[Audio]=None, document: Optional[Document]=None, photo: Optional[List[PhotoSize]]=None, - sticker: Optional[Sticker]=None, story: Optional[Story]=None, video: Optional[Video]=None, - video_note: Optional[VideoNote]=None, voice: Optional[Voice]=None, - has_media_spoiler: Optional[bool]=None, contact: Optional[Contact]=None, - dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None, - giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None, - location: Optional[Location]=None, poll: Optional[Poll]=None, - venue: Optional[Venue]=None) -> None: + def __init__( + self, origin: MessageOrigin, chat: Optional[Chat]=None, message_id: Optional[int]=None, + link_preview_options: Optional[LinkPreviewOptions]=None, animation: Optional[Animation]=None, + audio: Optional[Audio]=None, document: Optional[Document]=None, photo: Optional[List[PhotoSize]]=None, + sticker: Optional[Sticker]=None, story: Optional[Story]=None, video: Optional[Video]=None, + video_note: Optional[VideoNote]=None, voice: Optional[Voice]=None, + has_media_spoiler: Optional[bool]=None, contact: Optional[Contact]=None, + dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None, + giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None, + location: Optional[Location]=None, poll: Optional[Poll]=None, + venue: Optional[Venue]=None) -> None: self.origin: MessageOrigin = origin - self.chat: Optional[Chat] = chat self.message_id: Optional[int] = message_id self.link_preview_options: Optional[LinkPreviewOptions] = link_preview_options @@ -8425,8 +8381,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - message_type = obj.get('type') + message_type = obj['type'] if message_type == 'user': sender_user = User.de_json(obj['sender_user']) return MessageOriginUser(date=obj['date'], sender_user=sender_user) @@ -8538,10 +8493,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - #todo: adopt to common way - return cls(is_disabled=obj.get('is_disabled'), url=obj.get('url'), prefer_small_media=obj.get('prefer_small_media'), - prefer_large_media=obj.get('prefer_large_media'), show_above_text=obj.get('show_above_text')) - + return cls(**obj) def __init__(self, is_disabled: Optional[bool] = None, url: Optional[str] = None, prefer_small_media: Optional[bool] = None, prefer_large_media: Optional[bool] = None, @@ -8565,7 +8517,7 @@ def to_dict(self) -> dict: json_dict['prefer_large_media'] = self.prefer_large_media if self.show_above_text is not None: json_dict['show_above_text'] = self.show_above_text - + return json_dict def to_json(self) -> str: return json.dumps(self.to_dict()) @@ -8610,7 +8562,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - self.chats = [Chat.de_json(chat) for chat in obj['chats']] + obj['chats'] = [Chat.de_json(chat) for chat in obj['chats']] return cls(**obj) def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: int, @@ -8765,11 +8717,13 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['entities'] = [MessageEntity.de_json(entity) for entity in obj.get('entities', [])] + if 'entities' in obj: + obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] return cls(**obj) - def __init__(self, text: str, entities: Optional[List[MessageEntity]] = None, - position: Optional[int] = None, is_manual: Optional[bool] = None) -> None: + def __init__(self, text: str, position: int, + entities: Optional[List[MessageEntity]] = None, + is_manual: Optional[bool] = None) -> None: self.text: str = text self.entities: Optional[List[MessageEntity]] = entities self.position: Optional[int] = position @@ -8812,7 +8766,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj.get('quote_entities', [])] + if 'quote_entities' in obj: + obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj['quote_entities']] return cls(**obj) def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, @@ -8968,7 +8923,8 @@ class ChatBoostSource(JsonDeserializable): def de_json(cls, json_string): if json_string is None: return None - return cls(**cls.check_json(json_string)) + obj = cls.check_json(json_string) + return cls(**obj) def __init__(self, source): self.source = source From 391a7e9f59e783efca3cc32c0fba8417b918d21b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 16:57:47 +0300 Subject: [PATCH 099/480] Add Python 3.12 to supported versions. --- .github/workflows/setup_python.yml | 2 +- .travis.yml | 1 + README.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index 2a9787e25..0276c0026 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] name: ${{ matrix.python-version }} and tests steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index 8e6b02e5c..1fe9399d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - "3.9" - "3.10" - "3.11" + - "3.12" - "pypy3" install: "pip install -r requirements.txt" script: diff --git a/README.md b/README.md index 289e38d7a..bcc07fa47 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ## Getting started -This API is tested with Python 3.8-3.11 and Pypy 3. +This API is tested with Python 3.8-3.12 and Pypy 3. There are two ways to install the library: * Installation using pip (a Python package manager): From 9a2c70460fa8f9a0ae38c45ee0825d20b41751b5 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 17:28:54 +0300 Subject: [PATCH 100/480] Rollback python 3.12 --- .github/workflows/setup_python.yml | 2 +- .travis.yml | 1 - README.md | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index 0276c0026..2a9787e25 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] + python-version: [ '3.8', '3.9', '3.10', '3.11', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] name: ${{ matrix.python-version }} and tests steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index 1fe9399d6..8e6b02e5c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ python: - "3.9" - "3.10" - "3.11" - - "3.12" - "pypy3" install: "pip install -r requirements.txt" script: diff --git a/README.md b/README.md index bcc07fa47..289e38d7a 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ## Getting started -This API is tested with Python 3.8-3.12 and Pypy 3. +This API is tested with Python 3.8-3.11 and Pypy 3. There are two ways to install the library: * Installation using pip (a Python package manager): From a1ac42f35452b8046e8400846137dca1a218098a Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 17:59:27 +0300 Subject: [PATCH 101/480] Deprecation fixes #1 --- telebot/types.py | 173 +++++++++++++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 65 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 6f88621d1..c575b3770 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -811,29 +811,26 @@ class Message(JsonDeserializable): :param chat: Conversation the message belongs to :type chat: :class:`telebot.types.Chat` - :param forward_from: Optional. For forwarded messages, sender of the original message + :param forward_from: deprecated. :type forward_from: :class:`telebot.types.User` - :param forward_from_chat: Optional. For messages forwarded from channels or from anonymous administrators, - information about the original sender chat + :param forward_from_chat: deprecated. :type forward_from_chat: :class:`telebot.types.Chat` - :param forward_from_message_id: Optional. For messages forwarded from channels, identifier of the original + :param forward_from_message_id: deprecated. message in the channel :type forward_from_message_id: :obj:`int` - :param forward_signature: Optional. For forwarded messages that were originally sent in channels or by an - anonymous chat administrator, signature of the message sender if present + :param forward_signature: deprecated. :type forward_signature: :obj:`str` - :param forward_sender_name: Optional. Sender's name for messages forwarded from users who disallow adding a link - to their account in forwarded messages + :param forward_sender_name: deprecated. :type forward_sender_name: :obj:`str` - :param forward_date: Optional. For forwarded messages, date the original message was sent in Unix time + :param forward_date: deprecated. :type forward_date: :obj:`int` - :forward_origin: Optional. For forwarded messages, information about the original message; + :forward_origin: Optional. For forwarded messages, information about the original message; :type forward_origin: :class:`telebot.types.MessageOrigin` :param is_topic_message: Optional. True, if the message is sent to a forum topic @@ -1079,18 +1076,6 @@ def de_json(cls, json_string): opts = {} if 'sender_chat' in obj: opts['sender_chat'] = Chat.de_json(obj['sender_chat']) - if 'forward_from' in obj: - opts['forward_from'] = User.de_json(obj['forward_from']) - if 'forward_from_chat' in obj: - opts['forward_from_chat'] = Chat.de_json(obj['forward_from_chat']) - if 'forward_from_message_id' in obj: - opts['forward_from_message_id'] = obj.get('forward_from_message_id') - if 'forward_signature' in obj: - opts['forward_signature'] = obj.get('forward_signature') - if 'forward_sender_name' in obj: - opts['forward_sender_name'] = obj.get('forward_sender_name') - if 'forward_date' in obj: - opts['forward_date'] = obj.get('forward_date') if 'is_automatic_forward' in obj: opts['is_automatic_forward'] = obj.get('is_automatic_forward') if 'is_topic_message' in obj: @@ -1123,8 +1108,7 @@ def de_json(cls, json_string): opts['document'] = Document.de_json(obj['document']) content_type = 'document' if 'animation' in obj: - # Document content type accompanies "animation", - # so "animation" should be checked below "document" to override it + # Document content type accompanies "animation", so "animation" should be checked after "document" to override it opts['animation'] = Animation.de_json(obj['animation']) content_type = 'animation' if 'game' in obj: @@ -1216,19 +1200,15 @@ def de_json(cls, json_string): content_type = 'proximity_alert_triggered' if 'video_chat_scheduled' in obj: opts['video_chat_scheduled'] = VideoChatScheduled.de_json(obj['video_chat_scheduled']) - opts['voice_chat_scheduled'] = opts['video_chat_scheduled'] # deprecated, for backward compatibility content_type = 'video_chat_scheduled' if 'video_chat_started' in obj: opts['video_chat_started'] = VideoChatStarted.de_json(obj['video_chat_started']) - opts['voice_chat_started'] = opts['video_chat_started'] # deprecated, for backward compatibility content_type = 'video_chat_started' if 'video_chat_ended' in obj: opts['video_chat_ended'] = VideoChatEnded.de_json(obj['video_chat_ended']) - opts['voice_chat_ended'] = opts['video_chat_ended'] # deprecated, for backward compatibility content_type = 'video_chat_ended' if 'video_chat_participants_invited' in obj: opts['video_chat_participants_invited'] = VideoChatParticipantsInvited.de_json(obj['video_chat_participants_invited']) - opts['voice_chat_participants_invited'] = opts['video_chat_participants_invited'] # deprecated, for backward compatibility content_type = 'video_chat_participants_invited' if 'web_app_data' in obj: opts['web_app_data'] = WebAppData.de_json(obj['web_app_data']) @@ -1288,8 +1268,8 @@ def de_json(cls, json_string): if 'giveaway_completed' in obj: opts['giveaway_completed'] = GiveawayCompleted.de_json(obj['giveaway_completed']) content_type = 'giveaway_completed' - if 'message_origin' in obj: - opts['message_origin'] = MessageOrigin.de_json(obj['message_origin']) + if 'forward_origin' in obj: + opts['forward_origin'] = MessageOrigin.de_json(obj['forward_origin']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1331,12 +1311,6 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.date: int = date self.chat: Chat = chat self.sender_chat: Optional[Chat] = None - self.forward_from: Optional[User] = None - self.forward_from_chat: Optional[Chat] = None - self.forward_from_message_id: Optional[int] = None - self.forward_signature: Optional[str] = None - self.forward_sender_name: Optional[str] = None - self.forward_date: Optional[int] = None self.is_automatic_forward: Optional[bool] = None self.reply_to_message: Optional[Message] = None self.via_bot: Optional[User] = None @@ -1512,11 +1486,78 @@ def html_caption(self): """ return self.__html_text(self.caption, self.caption_entities) + @property + def voice_chat_scheduled(self): + logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') + return self.video_chat_scheduled + + @property + def voice_chat_started(self): + logger.warning('The parameter "voice_chat_started" is deprecated, use "video_chat_started" instead') + return self.video_chat_started + + @property + def voice_chat_ended(self): + logger.warning('The parameter "voice_chat_ended" is deprecated, use "video_chat_ended" instead') + return self.video_chat_ended + + @property + def voice_chat_participants_invited(self): + logger.warning('The parameter "voice_chat_participants_invited" is deprecated, use "video_chat_participants_invited" instead') + return self.video_chat_participants_invited + @property def new_chat_member(self): logger.warning('The parameter "new_chat_member" is deprecated, use "new_chat_members" instead') return None + @property + def forward_from(self): + logger.warning('The parameter "forward_from" is deprecated, use "forward_origin" instead') + if self.forward_origin and isinstance(self.forward_origin, MessageOriginUser): + return self.forward_origin.sender_user + return None + + @property + def forward_from_chat(self): + logger.warning('The parameter "forward_from_chat" is deprecated, use "forward_origin" instead') + if self.forward_origin and isinstance(self.forward_origin, MessageOriginChat): + return self.forward_origin.sender_chat + elif self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): + return self.forward_origin.chat + return None + + @property + def forward_from_message_id(self): + logger.warning('The parameter "forward_from_message_id" is deprecated, use "forward_origin" instead') + if self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): + return self.forward_origin.message_id + return None + + @property + def forward_signature(self): + logger.warning('The parameter "forward_signature" is deprecated, use "forward_origin" instead') + if self.forward_origin and isinstance(self.forward_origin, MessageOriginChat): + return self.forward_origin.author_signature + elif self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): + return self.forward_origin.author_signature + return None + + @property + def forward_sender_name(self): + logger.warning('The parameter "forward_sender_name" is deprecated, use "forward_origin" instead') + if self.forward_origin and isinstance(self.forward_origin, MessageOriginHiddenUser): + return self.forward_origin.sender_user_name + return None + + @property + def forward_date(self): + logger.warning('The parameter "forward_date" is deprecated, use "forward_origin" instead') + if self.forward_origin: + return self.forward_origin.date + return None + + class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): """ @@ -3031,13 +3072,11 @@ def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_ed self.can_pin_messages: bool = can_pin_messages self.is_member: bool = is_member self.can_send_messages: bool = can_send_messages - #self.can_send_media_messages: bool = can_send_media_messages self.can_send_polls: bool = can_send_polls self.can_send_other_messages: bool = can_send_other_messages self.can_add_web_page_previews: bool = can_add_web_page_previews self.can_manage_chat: bool = can_manage_chat self.can_manage_video_chats: bool = can_manage_video_chats - self.can_manage_voice_chats: bool = self.can_manage_video_chats # deprecated, for backward compatibility self.until_date: int = until_date self.can_manage_topics: bool = can_manage_topics self.can_send_audios: bool = can_send_audios @@ -3049,7 +3088,12 @@ def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_ed self.can_post_stories: bool = can_post_stories self.can_edit_stories: bool = can_edit_stories self.can_delete_stories: bool = can_delete_stories - + + @property + def can_manage_voice_chats(self): + logger.warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') + return self.can_manage_video_chats + class ChatMemberOwner(ChatMember): @@ -3330,8 +3374,7 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): value of can_pin_messages :type can_manage_topics: :obj:`bool` - :param can_send_media_messages: deprecated. True, if the user is allowed to send audios, documents, photos, videos, - video notes and voice notes + :param can_send_media_messages: deprecated. :type can_send_media_messages: :obj:`bool` :return: Instance of the class @@ -3351,7 +3394,6 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send can_invite_users=None, can_pin_messages=None, can_manage_topics=None, **kwargs): self.can_send_messages: bool = can_send_messages - #self.can_send_media_messages: bool = can_send_media_messages self.can_send_polls: bool = can_send_polls self.can_send_other_messages: bool = can_send_other_messages self.can_add_web_page_previews: bool = can_add_web_page_previews @@ -3367,7 +3409,7 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send self.can_send_voice_notes: bool = can_send_voice_notes if can_send_media_messages is not None: - logger.warning("can_send_media_messages is deprecated. Use individual parameters like can_send_audios, can_send_documents, etc.") + logger.warning('The parameter "can_send_media_messages" is deprecated. Use individual parameters like "can_send_audios", "can_send_documents" etc.') self.can_send_audios = can_send_media_messages self.can_send_documents = can_send_media_messages self.can_send_photos = can_send_media_messages @@ -3712,9 +3754,12 @@ class InputTextMessageContent(Dictionaryable): parse_mode :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param disable_web_page_preview: Optional, deprecated. Disables link previews for links in the sent message + :param disable_web_page_preview: deprecated :type disable_web_page_preview: :obj:`bool` + :param link_preview_options: Optional. Link preview generation options for the message + :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :return: Instance of the class :rtype: :class:`telebot.types.InputTextMessageContent` """ @@ -3724,10 +3769,10 @@ def __init__(self, message_text, parse_mode=None, entities=None, disable_web_pag self.entities: List[MessageEntity] = entities link_preview_options: LinkPreviewOptions = link_preview_options if disable_web_page_preview is not None: - logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + logger.warning('The parameter "disable_web_page_preview" is deprecated. Use "link_preview_options" instead.') if link_preview_options: - logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") + logger.warning('Both "link_preview_options" and "disable_web_page_preview" parameters are set: conflicting, "disable_web_page_preview" is deprecated') else: self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(disable_web_page_preview) @@ -5645,7 +5690,7 @@ class Game(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['photo'] = Game.parse_photo(obj['photo']) if 'text_entities' in obj: @@ -5724,7 +5769,7 @@ class Animation(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) if 'thumbnail' in obj and 'file_id' in obj['thumbnail']: obj["thumbnail"] = PhotoSize.de_json(obj['thumbnail']) @@ -5770,7 +5815,7 @@ class GameHighScore(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) return cls(**obj) @@ -5841,7 +5886,7 @@ class Invoice(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) @@ -5882,7 +5927,7 @@ class ShippingAddress(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) @@ -5918,7 +5963,7 @@ class OrderInfo(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['shipping_address'] = ShippingAddress.de_json(obj.get('shipping_address')) return cls(**obj) @@ -6008,7 +6053,7 @@ class SuccessfulPayment(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['order_info'] = OrderInfo.de_json(obj.get('order_info')) return cls(**obj) @@ -6047,7 +6092,7 @@ class ShippingQuery(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj.pop('from')) obj['shipping_address'] = ShippingAddress.de_json(obj['shipping_address']) @@ -6094,7 +6139,7 @@ class PreCheckoutQuery(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj.pop('from')) obj['order_info'] = OrderInfo.de_json(obj.get('order_info')) @@ -6133,8 +6178,7 @@ class StickerSet(JsonDeserializable): :param is_video: True, if the sticker set contains video stickers :type is_video: :obj:`bool` - :param contains_masks: True, if the sticker set contains masks. Deprecated since Bot API 6.2, - use sticker_type instead. + :param contains_masks: deprecated :type contains_masks: :obj:`bool` :param stickers: List of all set stickers @@ -6148,7 +6192,7 @@ class StickerSet(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) stickers = [] for s in obj['stickers']: @@ -6179,7 +6223,7 @@ def contains_masks(self): """ Deprecated since Bot API 6.2, use sticker_type instead. """ - logger.warning("contains_masks is deprecated, use sticker_type instead") + logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type instead"') return self.sticker_type == 'mask' @@ -6244,7 +6288,7 @@ class Sticker(JsonDeserializable): @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) if 'thumbnail' in obj and 'file_id' in obj['thumbnail']: obj['thumbnail'] = PhotoSize.de_json(obj['thumbnail']) @@ -6308,7 +6352,7 @@ class MaskPosition(Dictionaryable, JsonDeserializable, JsonSerializable): @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) @@ -6714,7 +6758,7 @@ class PollOption(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) @@ -6780,7 +6824,7 @@ class Poll(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) obj['poll_id'] = obj.pop('id') options = [] @@ -6806,7 +6850,6 @@ def __init__( self.is_anonymous: bool = is_anonymous self.type: str = type if poll_type is not None: - # Wrong param name backward compatibility logger.warning("Poll: poll_type parameter is deprecated. Use type instead.") if type is None: self.type: str = poll_type @@ -6854,7 +6897,7 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): """ @classmethod def de_json(cls, json_string): - if (json_string is None): return None + if json_string is None: return None obj = cls.check_json(json_string) if 'user' in obj: obj['user'] = User.de_json(obj['user']) From cf176a93d3bdb51167052f8f5b7f8f190a051370 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 18:39:36 +0300 Subject: [PATCH 102/480] Added hint (for me) and kwargs (for safety) --- telebot/types.py | 559 ++++++++++++++++++++++++++--------------------- 1 file changed, 306 insertions(+), 253 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index c575b3770..58843f7e3 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -19,7 +19,6 @@ logger = logging.getLogger('TeleBot') - class JsonSerializable(object): """ Subclasses of this class are guaranteed to be able to be converted to JSON format. @@ -692,7 +691,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, - profile_background_custom_emoji_id=None, has_visible_history=None,**kwargs): + profile_background_custom_emoji_id=None, has_visible_history=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -770,300 +769,301 @@ class WebAppData(JsonDeserializable, Dictionaryable): :rtype: :class:`telebot.types.WebAppData` """ - def __init__(self, data, button_text): - self.data = data - self.button_text = button_text - def to_dict(self): - return {'data': self.data, 'button_text': self.button_text} - @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) + def __init__(self, data, button_text, **kwargs): + self.data = data + self.button_text = button_text + def to_dict(self): + return {'data': self.data, 'button_text': self.button_text} + +# noinspection PyUnresolvedReferences class Message(JsonDeserializable): """ - This object represents a message. + This object represents a message. - Telegram Documentation: https://core.telegram.org/bots/api#message + Telegram Documentation: https://core.telegram.org/bots/api#message - :param message_id: Unique message identifier inside this chat - :type message_id: :obj:`int` + :param message_id: Unique message identifier inside this chat + :type message_id: :obj:`int` - :param message_thread_id: Optional. Unique identifier of a message thread to which the message belongs; for supergroups only - :type message_thread_id: :obj:`int` + :param message_thread_id: Optional. Unique identifier of a message thread to which the message belongs; for supergroups only + :type message_thread_id: :obj:`int` - :param from_user: Optional. Sender of the message; empty for messages sent to channels. For backward compatibility, the - field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. - :type from_user: :class:`telebot.types.User` + :param from_user: Optional. Sender of the message; empty for messages sent to channels. For backward compatibility, the + field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. + :type from_user: :class:`telebot.types.User` - :param sender_chat: Optional. Sender of the message, sent on behalf of a chat. For example, the channel itself for - channel posts, the supergroup itself for messages from anonymous group administrators, the linked channel for - messages automatically forwarded to the discussion group. For backward compatibility, the field from contains a - fake sender user in non-channel chats, if the message was sent on behalf of a chat. - :type sender_chat: :class:`telebot.types.Chat` + :param sender_chat: Optional. Sender of the message, sent on behalf of a chat. For example, the channel itself for + channel posts, the supergroup itself for messages from anonymous group administrators, the linked channel for + messages automatically forwarded to the discussion group. For backward compatibility, the field from contains a + fake sender user in non-channel chats, if the message was sent on behalf of a chat. + :type sender_chat: :class:`telebot.types.Chat` - :param date: Date the message was sent in Unix time - :type date: :obj:`int` + :param date: Date the message was sent in Unix time + :type date: :obj:`int` - :param chat: Conversation the message belongs to - :type chat: :class:`telebot.types.Chat` + :param chat: Conversation the message belongs to + :type chat: :class:`telebot.types.Chat` - :param forward_from: deprecated. - :type forward_from: :class:`telebot.types.User` + :param forward_from: deprecated. + :type forward_from: :class:`telebot.types.User` - :param forward_from_chat: deprecated. - :type forward_from_chat: :class:`telebot.types.Chat` + :param forward_from_chat: deprecated. + :type forward_from_chat: :class:`telebot.types.Chat` - :param forward_from_message_id: deprecated. - message in the channel - :type forward_from_message_id: :obj:`int` + :param forward_from_message_id: deprecated. + message in the channel + :type forward_from_message_id: :obj:`int` - :param forward_signature: deprecated. - :type forward_signature: :obj:`str` + :param forward_signature: deprecated. + :type forward_signature: :obj:`str` - :param forward_sender_name: deprecated. - :type forward_sender_name: :obj:`str` + :param forward_sender_name: deprecated. + :type forward_sender_name: :obj:`str` - :param forward_date: deprecated. - :type forward_date: :obj:`int` + :param forward_date: deprecated. + :type forward_date: :obj:`int` - :forward_origin: Optional. For forwarded messages, information about the original message; - :type forward_origin: :class:`telebot.types.MessageOrigin` + :forward_origin: Optional. For forwarded messages, information about the original message; + :type forward_origin: :class:`telebot.types.MessageOrigin` - :param is_topic_message: Optional. True, if the message is sent to a forum topic - :type is_topic_message: :obj:`bool` + :param is_topic_message: Optional. True, if the message is sent to a forum topic + :type is_topic_message: :obj:`bool` - :param is_automatic_forward: Optional. :obj:`bool`, if the message is a channel post that was automatically - forwarded to the connected discussion group - :type is_automatic_forward: :obj:`bool` + :param is_automatic_forward: Optional. :obj:`bool`, if the message is a channel post that was automatically + forwarded to the connected discussion group + :type is_automatic_forward: :obj:`bool` - :param reply_to_message: Optional. For replies, the original message. Note that the Message object in this field - will not contain further reply_to_message fields even if it itself is a reply. - :type reply_to_message: :class:`telebot.types.Message` + :param reply_to_message: Optional. For replies, the original message. Note that the Message object in this field + will not contain further reply_to_message fields even if it itself is a reply. + :type reply_to_message: :class:`telebot.types.Message` - :param external_reply: Optional. Information about the message that is being replied to, which may come from another chat or forum topic - :type external_reply: :class:`telebot.types.ExternalReplyInfo` + :param external_reply: Optional. Information about the message that is being replied to, which may come from another chat or forum topic + :type external_reply: :class:`telebot.types.ExternalReplyInfo` - :param quote: Optional. For replies that quote part of the original message, the quoted part of the message - :type quote: :class:`telebot.types.TextQuote` + :param quote: Optional. For replies that quote part of the original message, the quoted part of the message + :type quote: :class:`telebot.types.TextQuote` - :param via_bot: Optional. Bot through which the message was sent - :type via_bot: :class:`telebot.types.User` + :param via_bot: Optional. Bot through which the message was sent + :type via_bot: :class:`telebot.types.User` - :param edit_date: Optional. Date the message was last edited in Unix time - :type edit_date: :obj:`int` + :param edit_date: Optional. Date the message was last edited in Unix time + :type edit_date: :obj:`int` - :param has_protected_content: Optional. :obj:`bool`, if the message can't be forwarded - :type has_protected_content: :obj:`bool` + :param has_protected_content: Optional. :obj:`bool`, if the message can't be forwarded + :type has_protected_content: :obj:`bool` - :param media_group_id: Optional. The unique identifier of a media message group this message belongs to - :type media_group_id: :obj:`str` + :param media_group_id: Optional. The unique identifier of a media message group this message belongs to + :type media_group_id: :obj:`str` - :param author_signature: Optional. Signature of the post author for messages in channels, or the custom title of an - anonymous group administrator - :type author_signature: :obj:`str` + :param author_signature: Optional. Signature of the post author for messages in channels, or the custom title of an + anonymous group administrator + :type author_signature: :obj:`str` - :param text: Optional. For text messages, the actual UTF-8 text of the message - :type text: :obj:`str` + :param text: Optional. For text messages, the actual UTF-8 text of the message + :type text: :obj:`str` - :param entities: Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that - appear in the text - :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :param entities: Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that + appear in the text + :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param link_preview_options: Optional. Options used for link preview generation for the message, - if it is a text message and link preview options were changed - :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param link_preview_options: Optional. Options used for link preview generation for the message, + if it is a text message and link preview options were changed + :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` - :param animation: Optional. Message is an animation, information about the animation. For backward - compatibility, when this field is set, the document field will also be set - :type animation: :class:`telebot.types.Animation` + :param animation: Optional. Message is an animation, information about the animation. For backward + compatibility, when this field is set, the document field will also be set + :type animation: :class:`telebot.types.Animation` - :param audio: Optional. Message is an audio file, information about the file - :type audio: :class:`telebot.types.Audio` + :param audio: Optional. Message is an audio file, information about the file + :type audio: :class:`telebot.types.Audio` - :param document: Optional. Message is a general file, information about the file - :type document: :class:`telebot.types.Document` + :param document: Optional. Message is a general file, information about the file + :type document: :class:`telebot.types.Document` - :param photo: Optional. Message is a photo, available sizes of the photo - :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` + :param photo: Optional. Message is a photo, available sizes of the photo + :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` - :param sticker: Optional. Message is a sticker, information about the sticker - :type sticker: :class:`telebot.types.Sticker` + :param sticker: Optional. Message is a sticker, information about the sticker + :type sticker: :class:`telebot.types.Sticker` - :param story: Optional. Message is a forwarded story - :type story: :class:`telebot.types.Story` + :param story: Optional. Message is a forwarded story + :type story: :class:`telebot.types.Story` - :param video: Optional. Message is a video, information about the video - :type video: :class:`telebot.types.Video` + :param video: Optional. Message is a video, information about the video + :type video: :class:`telebot.types.Video` - :param video_note: Optional. Message is a video note, information about the video message - :type video_note: :class:`telebot.types.VideoNote` + :param video_note: Optional. Message is a video note, information about the video message + :type video_note: :class:`telebot.types.VideoNote` - :param voice: Optional. Message is a voice message, information about the file - :type voice: :class:`telebot.types.Voice` + :param voice: Optional. Message is a voice message, information about the file + :type voice: :class:`telebot.types.Voice` - :param caption: Optional. Caption for the animation, audio, document, photo, video or voice - :type caption: :obj:`str` + :param caption: Optional. Caption for the animation, audio, document, photo, video or voice + :type caption: :obj:`str` - :param caption_entities: Optional. For messages with a caption, special entities like usernames, URLs, bot - commands, etc. that appear in the caption - :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :param caption_entities: Optional. For messages with a caption, special entities like usernames, URLs, bot + commands, etc. that appear in the caption + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation - :type has_media_spoiler: :obj:`bool` + :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation + :type has_media_spoiler: :obj:`bool` - :param contact: Optional. Message is a shared contact, information about the contact - :type contact: :class:`telebot.types.Contact` + :param contact: Optional. Message is a shared contact, information about the contact + :type contact: :class:`telebot.types.Contact` - :param dice: Optional. Message is a dice with random value - :type dice: :class:`telebot.types.Dice` + :param dice: Optional. Message is a dice with random value + :type dice: :class:`telebot.types.Dice` - :param game: Optional. Message is a game, information about the game. More about games » - :type game: :class:`telebot.types.Game` + :param game: Optional. Message is a game, information about the game. More about games » + :type game: :class:`telebot.types.Game` - :param poll: Optional. Message is a native poll, information about the poll - :type poll: :class:`telebot.types.Poll` + :param poll: Optional. Message is a native poll, information about the poll + :type poll: :class:`telebot.types.Poll` - :param venue: Optional. Message is a venue, information about the venue. For backward compatibility, when this - field is set, the location field will also be set - :type venue: :class:`telebot.types.Venue` + :param venue: Optional. Message is a venue, information about the venue. For backward compatibility, when this + field is set, the location field will also be set + :type venue: :class:`telebot.types.Venue` - :param location: Optional. Message is a shared location, information about the location - :type location: :class:`telebot.types.Location` + :param location: Optional. Message is a shared location, information about the location + :type location: :class:`telebot.types.Location` - :param new_chat_members: Optional. New members that were added to the group or supergroup and information about - them (the bot itself may be one of these members) - :type new_chat_members: :obj:`list` of :class:`telebot.types.User` + :param new_chat_members: Optional. New members that were added to the group or supergroup and information about + them (the bot itself may be one of these members) + :type new_chat_members: :obj:`list` of :class:`telebot.types.User` - :param left_chat_member: Optional. A member was removed from the group, information about them (this member may be - the bot itself) - :type left_chat_member: :class:`telebot.types.User` + :param left_chat_member: Optional. A member was removed from the group, information about them (this member may be + the bot itself) + :type left_chat_member: :class:`telebot.types.User` - :param new_chat_title: Optional. A chat title was changed to this value - :type new_chat_title: :obj:`str` + :param new_chat_title: Optional. A chat title was changed to this value + :type new_chat_title: :obj:`str` - :param new_chat_photo: Optional. A chat photo was change to this value - :type new_chat_photo: :obj:`list` of :class:`telebot.types.PhotoSize` + :param new_chat_photo: Optional. A chat photo was change to this value + :type new_chat_photo: :obj:`list` of :class:`telebot.types.PhotoSize` - :param delete_chat_photo: Optional. Service message: the chat photo was deleted - :type delete_chat_photo: :obj:`bool` + :param delete_chat_photo: Optional. Service message: the chat photo was deleted + :type delete_chat_photo: :obj:`bool` - :param group_chat_created: Optional. Service message: the group has been created - :type group_chat_created: :obj:`bool` + :param group_chat_created: Optional. Service message: the group has been created + :type group_chat_created: :obj:`bool` - :param supergroup_chat_created: Optional. Service message: the supergroup has been created. This field can't be - received in a message coming through updates, because bot can't be a member of a supergroup when it is created. It can - only be found in reply_to_message if someone replies to a very first message in a directly created supergroup. - :type supergroup_chat_created: :obj:`bool` + :param supergroup_chat_created: Optional. Service message: the supergroup has been created. This field can't be + received in a message coming through updates, because bot can't be a member of a supergroup when it is created. It can + only be found in reply_to_message if someone replies to a very first message in a directly created supergroup. + :type supergroup_chat_created: :obj:`bool` - :param channel_chat_created: Optional. Service message: the channel has been created. This field can't be - received in a message coming through updates, because bot can't be a member of a channel when it is created. It can only - be found in reply_to_message if someone replies to a very first message in a channel. - :type channel_chat_created: :obj:`bool` + :param channel_chat_created: Optional. Service message: the channel has been created. This field can't be + received in a message coming through updates, because bot can't be a member of a channel when it is created. It can only + be found in reply_to_message if someone replies to a very first message in a channel. + :type channel_chat_created: :obj:`bool` - :param message_auto_delete_timer_changed: Optional. Service message: auto-delete timer settings changed in - the chat - :type message_auto_delete_timer_changed: :class:`telebot.types.MessageAutoDeleteTimerChanged` + :param message_auto_delete_timer_changed: Optional. Service message: auto-delete timer settings changed in + the chat + :type message_auto_delete_timer_changed: :class:`telebot.types.MessageAutoDeleteTimerChanged` - :param migrate_to_chat_id: Optional. The group has been migrated to a supergroup with the specified identifier. - This number may have more than 32 significant bits and some programming languages may have difficulty/silent - defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision - float type are safe for storing this identifier. - :type migrate_to_chat_id: :obj:`int` + :param migrate_to_chat_id: Optional. The group has been migrated to a supergroup with the specified identifier. + This number may have more than 32 significant bits and some programming languages may have difficulty/silent + defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision + float type are safe for storing this identifier. + :type migrate_to_chat_id: :obj:`int` - :param migrate_from_chat_id: Optional. The supergroup has been migrated from a group with the specified - identifier. This number may have more than 32 significant bits and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or - double-precision float type are safe for storing this identifier. - :type migrate_from_chat_id: :obj:`int` + :param migrate_from_chat_id: Optional. The supergroup has been migrated from a group with the specified + identifier. This number may have more than 32 significant bits and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + double-precision float type are safe for storing this identifier. + :type migrate_from_chat_id: :obj:`int` - :param pinned_message: Optional. Specified message was pinned. Note that the Message object in this field will not - contain further reply_to_message fields even if it is itself a reply. - :type pinned_message: :class:`telebot.types.Message` + :param pinned_message: Optional. Specified message was pinned. Note that the Message object in this field will not + contain further reply_to_message fields even if it is itself a reply. + :type pinned_message: :class:`telebot.types.Message` - :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » - :type invoice: :class:`telebot.types.Invoice` + :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » + :type invoice: :class:`telebot.types.Invoice` - :param successful_payment: Optional. Message is a service message about a successful payment, information about - the payment. More about payments » - :type successful_payment: :class:`telebot.types.SuccessfulPayment` + :param successful_payment: Optional. Message is a service message about a successful payment, information about + the payment. More about payments » + :type successful_payment: :class:`telebot.types.SuccessfulPayment` - :param users_shared: Optional. Service message: a user was shared with the bot - :type users_shared: :class:`telebot.types.UserShared` + :param users_shared: Optional. Service message: a user was shared with the bot + :type users_shared: :class:`telebot.types.UserShared` - :param chat_shared: Optional. Service message: a chat was shared with the bot - :type chat_shared: :class:`telebot.types.ChatShared` + :param chat_shared: Optional. Service message: a chat was shared with the bot + :type chat_shared: :class:`telebot.types.ChatShared` - :param connected_website: Optional. The domain name of the website on which the user has logged in. More about - Telegram Login » - :type connected_website: :obj:`str` + :param connected_website: Optional. The domain name of the website on which the user has logged in. More about + Telegram Login » + :type connected_website: :obj:`str` - :param write_access_allowed: Optional. Service message: the user allowed the bot added to the attachment - menu to write messages - :type write_access_allowed: :class:`telebot.types.WriteAccessAllowed` + :param write_access_allowed: Optional. Service message: the user allowed the bot added to the attachment + menu to write messages + :type write_access_allowed: :class:`telebot.types.WriteAccessAllowed` - :param passport_data: Optional. Telegram Passport data - :type passport_data: :class:`telebot.types.PassportData` + :param passport_data: Optional. Telegram Passport data + :type passport_data: :class:`telebot.types.PassportData` - :param proximity_alert_triggered: Optional. Service message. A user in the chat triggered another user's - proximity alert while sharing Live Location. - :type proximity_alert_triggered: :class:`telebot.types.ProximityAlertTriggered` + :param proximity_alert_triggered: Optional. Service message. A user in the chat triggered another user's + proximity alert while sharing Live Location. + :type proximity_alert_triggered: :class:`telebot.types.ProximityAlertTriggered` - :param forum_topic_created: Optional. Service message: forum topic created - :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` + :param forum_topic_created: Optional. Service message: forum topic created + :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` - :param forum_topic_edited: Optional. Service message: forum topic edited - :type forum_topic_edited: :class:`telebot.types.ForumTopicEdited` + :param forum_topic_edited: Optional. Service message: forum topic edited + :type forum_topic_edited: :class:`telebot.types.ForumTopicEdited` - :param forum_topic_closed: Optional. Service message: forum topic closed - :type forum_topic_closed: :class:`telebot.types.ForumTopicClosed` + :param forum_topic_closed: Optional. Service message: forum topic closed + :type forum_topic_closed: :class:`telebot.types.ForumTopicClosed` - :param forum_topic_reopened: Optional. Service message: forum topic reopened - :type forum_topic_reopened: :class:`telebot.types.ForumTopicReopened` + :param forum_topic_reopened: Optional. Service message: forum topic reopened + :type forum_topic_reopened: :class:`telebot.types.ForumTopicReopened` - :param general_forum_topic_hidden: Optional. Service message: the 'General' forum topic hidden - :type general_forum_topic_hidden: :class:`telebot.types.GeneralForumTopicHidden` + :param general_forum_topic_hidden: Optional. Service message: the 'General' forum topic hidden + :type general_forum_topic_hidden: :class:`telebot.types.GeneralForumTopicHidden` - :param general_forum_topic_unhidden: Optional. Service message: the 'General' forum topic unhidden - :type general_forum_topic_unhidden: :class:`telebot.types.GeneralForumTopicUnhidden` + :param general_forum_topic_unhidden: Optional. Service message: the 'General' forum topic unhidden + :type general_forum_topic_unhidden: :class:`telebot.types.GeneralForumTopicUnhidden` - :param giveaway_created: Optional. Service message: a giveaway has been created - :type giveaway_created: :class:`telebot.types.GiveawayCreated` + :param giveaway_created: Optional. Service message: a giveaway has been created + :type giveaway_created: :class:`telebot.types.GiveawayCreated` - :param giveaway: Optional. The message is a scheduled giveaway message - :type giveaway: :class:`telebot.types.Giveaway` + :param giveaway: Optional. The message is a scheduled giveaway message + :type giveaway: :class:`telebot.types.Giveaway` - :param giveaway_winners: Optional. Service message: giveaway winners(public winners) - :type giveaway_winners: :class:`telebot.types.GiveawayWinners` + :param giveaway_winners: Optional. Service message: giveaway winners(public winners) + :type giveaway_winners: :class:`telebot.types.GiveawayWinners` - :param giveaway_completed: Optional. Service message: giveaway completed, without public winners - :type giveaway_completed: :class:`telebot.types.GiveawayCompleted` + :param giveaway_completed: Optional. Service message: giveaway completed, without public winners + :type giveaway_completed: :class:`telebot.types.GiveawayCompleted` - :param video_chat_scheduled: Optional. Service message: video chat scheduled - :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` + :param video_chat_scheduled: Optional. Service message: video chat scheduled + :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` - :param video_chat_started: Optional. Service message: video chat started - :type video_chat_started: :class:`telebot.types.VideoChatStarted` + :param video_chat_started: Optional. Service message: video chat started + :type video_chat_started: :class:`telebot.types.VideoChatStarted` - :param video_chat_ended: Optional. Service message: video chat ended - :type video_chat_ended: :class:`telebot.types.VideoChatEnded` + :param video_chat_ended: Optional. Service message: video chat ended + :type video_chat_ended: :class:`telebot.types.VideoChatEnded` - :param video_chat_participants_invited: Optional. Service message: new participants invited to a video chat - :type video_chat_participants_invited: :class:`telebot.types.VideoChatParticipantsInvited` + :param video_chat_participants_invited: Optional. Service message: new participants invited to a video chat + :type video_chat_participants_invited: :class:`telebot.types.VideoChatParticipantsInvited` - :param web_app_data: Optional. Service message: data sent by a Web App - :type web_app_data: :class:`telebot.types.WebAppData` + :param web_app_data: Optional. Service message: data sent by a Web App + :type web_app_data: :class:`telebot.types.WebAppData` - :param reply_markup: Optional. Inline keyboard attached to the message. login_url buttons are represented as - ordinary url buttons. - :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` + :param reply_markup: Optional. Inline keyboard attached to the message. login_url buttons are represented as + ordinary url buttons. + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` - :return: Instance of the class - :rtype: :class:`telebot.types.Message` - """ + :return: Instance of the class + :rtype: :class:`telebot.types.Message` + """ @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -1489,21 +1489,25 @@ def html_caption(self): @property def voice_chat_scheduled(self): logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') + # noinspection PyUnresolvedReferences return self.video_chat_scheduled @property def voice_chat_started(self): logger.warning('The parameter "voice_chat_started" is deprecated, use "video_chat_started" instead') + # noinspection PyUnresolvedReferences return self.video_chat_started @property def voice_chat_ended(self): logger.warning('The parameter "voice_chat_ended" is deprecated, use "video_chat_ended" instead') + # noinspection PyUnresolvedReferences return self.video_chat_ended @property def voice_chat_participants_invited(self): logger.warning('The parameter "voice_chat_participants_invited" is deprecated, use "video_chat_participants_invited" instead') + # noinspection PyUnresolvedReferences return self.video_chat_participants_invited @property @@ -2197,6 +2201,7 @@ def __init__(self, file_id, file_unique_id, file_size=None, file_path=None, **kw self.file_path: str = file_path +# noinspection PyUnresolvedReferences class ForceReply(JsonSerializable): """ Upon receiving a message with this object, Telegram clients will display a reply interface to the user (act as if the user has selected the bot's message and tapped 'Reply'). This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. @@ -2232,6 +2237,7 @@ def to_json(self): return json.dumps(json_dict) +# noinspection PyUnresolvedReferences class ReplyKeyboardRemove(JsonSerializable): """ Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see ReplyKeyboardMarkup). @@ -2287,8 +2293,9 @@ def __init__(self, url, **kwargs): def to_dict(self): return {'url': self.url} - + +# noinspection PyUnresolvedReferences class ReplyKeyboardMarkup(JsonSerializable): """ This object represents a custom keyboard with reply options (see Introduction to bots for details and examples). @@ -3095,7 +3102,7 @@ def can_manage_voice_chats(self): return self.can_manage_video_chats - +# noinspection PyUnresolvedReferences class ChatMemberOwner(ChatMember): """ Represents a chat member that owns the chat and has all administrator privileges. @@ -3120,6 +3127,7 @@ class ChatMemberOwner(ChatMember): pass +# noinspection PyUnresolvedReferences class ChatMemberAdministrator(ChatMember): """ Represents a chat member that has some additional privileges. @@ -3195,6 +3203,7 @@ class ChatMemberAdministrator(ChatMember): pass +# noinspection PyUnresolvedReferences class ChatMemberMember(ChatMember): """ Represents a chat member that has no additional privileges or restrictions. @@ -3213,6 +3222,7 @@ class ChatMemberMember(ChatMember): pass +# noinspection PyUnresolvedReferences class ChatMemberRestricted(ChatMember): """ Represents a chat member that is under certain restrictions in the chat. Supergroups only. @@ -3281,6 +3291,7 @@ class ChatMemberRestricted(ChatMember): pass +# noinspection PyUnresolvedReferences class ChatMemberLeft(ChatMember): """ Represents a chat member that isn't currently a member of the chat, but may join it themselves. @@ -3299,6 +3310,7 @@ class ChatMemberLeft(ChatMember): pass +# noinspection PyUnresolvedReferences class ChatMemberBanned(ChatMember): """ Represents a chat member that was banned in the chat and can't return to the chat or view chat messages. @@ -3478,7 +3490,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - def __init__(self, command, description): + def __init__(self, command, description, **kwargs): self.command: str = command self.description: str = description @@ -3547,6 +3559,7 @@ def to_json(self): return json.dumps(json_dict) +# noinspection PyUnresolvedReferences class BotCommandScopeDefault(BotCommandScope): """ Represents the default scope of bot commands. Default commands are used if no commands with a narrower scope are specified for the user. @@ -3567,6 +3580,7 @@ def __init__(self): super(BotCommandScopeDefault, self).__init__(type='default') +# noinspection PyUnresolvedReferences class BotCommandScopeAllPrivateChats(BotCommandScope): """ Represents the scope of bot commands, covering all private chats. @@ -3586,6 +3600,7 @@ def __init__(self): super(BotCommandScopeAllPrivateChats, self).__init__(type='all_private_chats') +# noinspection PyUnresolvedReferences class BotCommandScopeAllGroupChats(BotCommandScope): """ Represents the scope of bot commands, covering all group and supergroup chats. @@ -3605,6 +3620,7 @@ def __init__(self): super(BotCommandScopeAllGroupChats, self).__init__(type='all_group_chats') +# noinspection PyUnresolvedReferences class BotCommandScopeAllChatAdministrators(BotCommandScope): """ Represents the scope of bot commands, covering all group and supergroup chat administrators. @@ -3624,6 +3640,7 @@ def __init__(self): super(BotCommandScopeAllChatAdministrators, self).__init__(type='all_chat_administrators') +# noinspection PyUnresolvedReferences class BotCommandScopeChat(BotCommandScope): """ Represents the scope of bot commands, covering a specific chat. @@ -3644,6 +3661,7 @@ def __init__(self, chat_id=None): super(BotCommandScopeChat, self).__init__(type='chat', chat_id=chat_id) +# noinspection PyUnresolvedReferences class BotCommandScopeChatAdministrators(BotCommandScope): """ Represents the scope of bot commands, covering all administrators of a specific group or supergroup chat. @@ -3664,6 +3682,7 @@ def __init__(self, chat_id=None): super(BotCommandScopeChatAdministrators, self).__init__(type='chat_administrators', chat_id=chat_id) +# noinspection PyUnresolvedReferences class BotCommandScopeChatMember(BotCommandScope): """ Represents the scope of bot commands, covering a specific member of a group or supergroup chat. @@ -4206,7 +4225,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, inline_message_id=None): + def __init__(self, inline_message_id=None, **kwargs): self.inline_message_id = inline_message_id def to_dict(self): @@ -4216,6 +4235,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultArticle(InlineQueryResultBase): """ Represents a link to an article or web page. @@ -4300,6 +4320,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultPhoto(InlineQueryResultBase): """ Represents a link to a photo. By default, this photo will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the photo. @@ -4379,6 +4400,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultGif(InlineQueryResultBase): """ Represents a link to an animated GIF file. By default, this animated GIF file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4471,6 +4493,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultMpeg4Gif(InlineQueryResultBase): """ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). By default, this animated MPEG-4 file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4563,6 +4586,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultVideo(InlineQueryResultBase): """ Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video. @@ -4654,6 +4678,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultAudio(InlineQueryResultBase): """ Represents a link to an MP3 audio file. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio. @@ -4718,6 +4743,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultVoice(InlineQueryResultBase): """ Represents a link to a voice recording in an .OGG container encoded with OPUS. By default, this voice recording will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the the voice message. @@ -4775,6 +4801,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultDocument(InlineQueryResultBase): """ Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. Currently, only .PDF and .ZIP files can be sent using this method. @@ -4871,6 +4898,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultLocation(InlineQueryResultBase): """ Represents a location on a map. By default, the location will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the location. @@ -4975,6 +5003,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultVenue(InlineQueryResultBase): """ Represents a venue. By default, the venue will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the venue. @@ -5083,6 +5112,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultContact(InlineQueryResultBase): """ Represents a contact with a phone number. By default, this contact will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the contact. @@ -5170,6 +5200,7 @@ def to_dict(self): return json_dict +# noinspection PyUnresolvedReferences class InlineQueryResultGame(InlineQueryResultBase): """ Represents a Game. @@ -5238,6 +5269,7 @@ def to_json(self): return json.dumps(json_dict) +# noinspection PyUnresolvedReferences class InlineQueryResultCachedPhoto(InlineQueryResultCachedBase): """ Represents a link to a photo stored on the Telegram servers. By default, this photo will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the photo. @@ -5296,6 +5328,7 @@ def __init__(self, id, photo_file_id, title=None, description=None, self.payload_dic['photo_file_id'] = photo_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedGif(InlineQueryResultCachedBase): """ Represents a link to an animated GIF file stored on the Telegram servers. By default, this animated GIF file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with specified content instead of the animation. @@ -5350,6 +5383,7 @@ def __init__(self, id, gif_file_id, title=None, description=None, self.payload_dic['gif_file_id'] = gif_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedMpeg4Gif(InlineQueryResultCachedBase): """ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) stored on the Telegram servers. By default, this animated MPEG-4 file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -5404,6 +5438,7 @@ def __init__(self, id, mpeg4_file_id, title=None, description=None, self.payload_dic['mpeg4_file_id'] = mpeg4_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedSticker(InlineQueryResultCachedBase): """ Represents a link to a sticker stored on the Telegram servers. By default, this sticker will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the sticker. @@ -5438,6 +5473,7 @@ def __init__(self, id, sticker_file_id, reply_markup=None, input_message_content self.payload_dic['sticker_file_id'] = sticker_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedDocument(InlineQueryResultCachedBase): """ Represents a link to a file stored on the Telegram servers. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. @@ -5496,6 +5532,7 @@ def __init__(self, id, document_file_id, title, description=None, self.payload_dic['document_file_id'] = document_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedVideo(InlineQueryResultCachedBase): """ Represents a link to a video file stored on the Telegram servers. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video. @@ -5555,6 +5592,7 @@ def __init__(self, id, video_file_id, title, description=None, self.payload_dic['video_file_id'] = video_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedVoice(InlineQueryResultCachedBase): """ Represents a link to a voice message stored on the Telegram servers. By default, this voice message will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the voice message. @@ -5608,6 +5646,7 @@ def __init__(self, id, voice_file_id, title, caption=None, caption_entities = No self.payload_dic['voice_file_id'] = voice_file_id +# noinspection PyUnresolvedReferences class InlineQueryResultCachedAudio(InlineQueryResultCachedBase): """ Represents a link to an MP3 audio file stored on the Telegram servers. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio. @@ -5975,6 +6014,7 @@ def __init__(self, name=None, phone_number=None, email=None, shipping_address=No self.shipping_address: ShippingAddress = shipping_address +# noinspection PyUnresolvedReferences class ShippingOption(JsonSerializable): """ This object represents one shipping option. @@ -6302,7 +6342,7 @@ def de_json(cls, json_string): def __init__(self, file_id, file_unique_id, type, width, height, is_animated, is_video, thumbnail=None, emoji=None, set_name=None, mask_position=None, file_size=None, - premium_animation=None, custom_emoji_id=None, needs_repainting=None ,**kwargs): + premium_animation=None, custom_emoji_id=None, needs_repainting=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.type: str = type @@ -7117,6 +7157,7 @@ def de_json(cls, json_string): def __init__(self, start_date, **kwargs): self.start_date: int = start_date + class VoiceChatScheduled(VideoChatScheduled): """ Deprecated, use :class:`VideoChatScheduled` instead. @@ -7147,6 +7188,7 @@ def de_json(cls, json_string): def __init__(self, duration, **kwargs): self.duration: int = duration + class VoiceChatEnded(VideoChatEnded): """ Deprecated, use :class:`VideoChatEnded` instead. @@ -7180,6 +7222,7 @@ def de_json(cls, json_string): def __init__(self, users=None, **kwargs): self.users: List[User] = users + class VoiceChatParticipantsInvited(VideoChatParticipantsInvited): """ Deprecated, use :class:`VideoChatParticipantsInvited` instead. @@ -7259,7 +7302,7 @@ class MenuButtonCommands(MenuButton): :rtype: :class:`telebot.types.MenuButtonCommands` """ - def __init__(self, type): + def __init__(self, type, **kwargs): self.type = type def to_dict(self): @@ -7268,6 +7311,7 @@ def to_dict(self): def to_json(self): return json.dumps(self.to_dict()) + class MenuButtonWebApp(MenuButton): """ Represents a menu button, which launches a Web App. @@ -7288,7 +7332,7 @@ class MenuButtonWebApp(MenuButton): :rtype: :class:`telebot.types.MenuButtonWebApp` """ - def __init__(self, type, text, web_app): + def __init__(self, type, text, web_app, **kwargs): self.type: str = type self.text: str = text self.web_app: WebAppInfo = web_app @@ -7298,6 +7342,7 @@ def to_dict(self): def to_json(self): return json.dumps(self.to_dict()) + class MenuButtonDefault(MenuButton): """ @@ -7311,7 +7356,7 @@ class MenuButtonDefault(MenuButton): :return: Instance of the class :rtype: :class:`telebot.types.MenuButtonDefault` """ - def __init__(self, type): + def __init__(self, type, **kwargs): self.type: str = type def to_dict(self): @@ -7393,7 +7438,7 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_post_messages: bool=None, can_edit_messages: bool=None, can_pin_messages: bool=None, can_manage_topics: bool=None, can_post_stories: bool=None, can_edit_stories: bool=None, - can_delete_stories: bool=None + can_delete_stories: bool=None, **kwargs ) -> None: self.is_anonymous: bool = is_anonymous @@ -7485,7 +7530,8 @@ class InputFile: def __init__(self, file) -> None: self._file, self.file_name = self._resolve_file(file) - def _resolve_file(self, file): + @staticmethod + def _resolve_file(file): if isinstance(file, str): _file = open(file, 'rb') return _file, os.path.basename(_file.name) @@ -7497,7 +7543,6 @@ def _resolve_file(self, file): else: raise TypeError("File must be a string or a file-like object(pathlib.Path, io.IOBase).") - @property def file(self): """ @@ -7530,7 +7575,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, name: str, icon_color: int, icon_custom_emoji_id: Optional[str]=None) -> None: + def __init__(self, name: str, icon_color: int, icon_custom_emoji_id: Optional[str]=None, **kwargs) -> None: self.name: str = name self.icon_color: int = icon_color self.icon_custom_emoji_id: Optional[str] = icon_custom_emoji_id @@ -7584,7 +7629,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, name: Optional[str]=None, icon_custom_emoji_id: Optional[str]=None) -> None: + def __init__(self, name: Optional[str]=None, icon_custom_emoji_id: Optional[str]=None, **kwargs) -> None: self.name: Optional[str] = name self.icon_custom_emoji_id: Optional[str] = icon_custom_emoji_id @@ -7649,7 +7694,8 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, message_thread_id: int, name: str, icon_color: int, icon_custom_emoji_id: Optional[str]=None) -> None: + def __init__(self, message_thread_id: int, name: str, icon_color: int, icon_custom_emoji_id: Optional[str]=None, + **kwargs) -> None: self.message_thread_id: int = message_thread_id self.name: str = name self.icon_color: int = icon_color @@ -7681,7 +7727,8 @@ def de_json(cls, json_string): return cls(**obj) - def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str]=None, from_attachment_menu: Optional[bool]=None) -> None: + def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str]=None, from_attachment_menu: Optional[bool]=None, + **kwargs) -> None: self.web_app_name: str = web_app_name self.from_request: bool = from_request self.from_attachment_menu: bool = from_attachment_menu @@ -7714,7 +7761,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, request_id: int, user_id: int) -> None: + def __init__(self, request_id: int, user_id: int, **kwargs) -> None: self.request_id: int = request_id self.user_id: int = user_id @@ -7746,7 +7793,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, request_id: int, chat_id: int) -> None: + def __init__(self, request_id: int, chat_id: int, **kwargs) -> None: self.request_id: int = request_id self.chat_id: int = chat_id @@ -7770,7 +7817,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, description: str) -> None: + def __init__(self, description: str, **kwargs) -> None: self.description: str = description @@ -7793,7 +7840,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, short_description: str) -> None: + def __init__(self, short_description: str, **kwargs) -> None: self.short_description: str = short_description @@ -7895,7 +7942,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, query=None, allow_user_chats=None, allow_bot_chats=None, allow_group_chats=None, - allow_channel_chats=None): + allow_channel_chats=None, **kwargs): self.query: str = query self.allow_user_chats: bool = allow_user_chats self.allow_bot_chats: bool = allow_bot_chats @@ -7942,7 +7989,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, name: str): + def __init__(self, name: str, **kwargs): self.name: str = name @@ -8007,7 +8054,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self) -> None: + def __init__(self, **kwargs) -> None: pass @@ -8049,8 +8096,9 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) - + +# noinspection PyUnresolvedReferences class ReactionTypeEmoji(ReactionType): """ This object represents an emoji reaction type. @@ -8067,16 +8115,17 @@ class ReactionTypeEmoji(ReactionType): :rtype: :class:`ReactionTypeEmoji` """ - def __init__(self, emoji: str) -> None: + def __init__(self, emoji: str, **kwargs) -> None: super().__init__('emoji') self.emoji: str = emoji def to_dict(self) -> dict: json_dict = super().to_dict() json_dict['emoji'] = self.emoji - return json_dict + return json_dict +# noinspection PyUnresolvedReferences class ReactionTypeCustomEmoji(ReactionType): """ This object represents a custom emoji reaction type. @@ -8093,7 +8142,7 @@ class ReactionTypeCustomEmoji(ReactionType): :rtype: :class:`ReactionTypeCustomEmoji` """ - def __init__(self, custom_emoji: str) -> None: + def __init__(self, custom_emoji: str, **kwargs) -> None: super().__init__('custom_emoji') self.custom_emoji: str = custom_emoji @@ -8150,7 +8199,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, chat: Chat, message_id: int, date: int, old_reaction: List[ReactionType], new_reaction: List[ReactionType], - user: Optional[User]=None, actor_chat: Optional[Chat]=None) -> None: + user: Optional[User]=None, actor_chat: Optional[Chat]=None, **kwargs) -> None: self.chat: Chat = chat self.message_id: int = message_id self.user: Optional[User] = user @@ -8192,7 +8241,7 @@ def de_json(cls, json_string): obj['reactions'] = [ReactionCount.de_json(reaction) for reaction in obj['reactions']] return cls(**obj) - def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[ReactionCount]) -> None: + def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[ReactionCount], **kwargs) -> None: self.chat: Chat = chat self.message_id: int = message_id self.date: int = date @@ -8223,7 +8272,7 @@ def de_json(cls, json_string): obj['type'] = ReactionType.de_json(obj['type']) return cls(**obj) - def __init__(self, type: ReactionType, total_count: int) -> None: + def __init__(self, type: ReactionType, total_count: int, **kwargs) -> None: self.type: ReactionType = type self.total_count: int = total_count @@ -8365,7 +8414,7 @@ def __init__( dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None, giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None, location: Optional[Location]=None, poll: Optional[Poll]=None, - venue: Optional[Venue]=None) -> None: + venue: Optional[Venue]=None, **kwargs) -> None: self.origin: MessageOrigin = origin self.chat: Optional[Chat] = chat self.message_id: Optional[int] = message_id @@ -8391,6 +8440,7 @@ def __init__( self.venue: Optional[Venue] = venue +# noinspection PyUnresolvedReferences class MessageOrigin(JsonDeserializable): """ This object describes the origin of a message. @@ -8540,7 +8590,7 @@ def de_json(cls, json_string): def __init__(self, is_disabled: Optional[bool] = None, url: Optional[str] = None, prefer_small_media: Optional[bool] = None, prefer_large_media: Optional[bool] = None, - show_above_text: Optional[bool] = None) -> None: + show_above_text: Optional[bool] = None, **kwargs) -> None: self.is_disabled: Optional[bool] = is_disabled self.url: Optional[str] = url self.prefer_small_media: Optional[bool] = prefer_small_media @@ -8611,7 +8661,7 @@ def de_json(cls, json_string): def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: int, only_new_members: Optional[bool] = None, has_public_winners: Optional[bool] = None, prize_description: Optional[str] = None, country_codes: Optional[List[str]] = None, - premium_subscription_month_count: Optional[int] = None) -> None: + premium_subscription_month_count: Optional[int] = None, **kwargs) -> None: self.chats: List[Chat] = chats self.winners_selection_date: int = winners_selection_date self.winner_count: int = winner_count @@ -8678,7 +8728,7 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: winners: List[User], additional_chat_count: Optional[int] = None, premium_subscription_month_count: Optional[int] = None, unclaimed_prize_count: Optional[int] = None, only_new_members: Optional[bool] = None, was_refunded: Optional[bool] = None, - prize_description: Optional[str] = None) -> None: + prize_description: Optional[str] = None, **kwargs) -> None: self.chat: Chat = chat self.giveaway_message_id: int = giveaway_message_id self.winners_selection_date: int = winners_selection_date @@ -8721,7 +8771,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = None, - giveaway_message: Optional[Message] = None) -> None: + giveaway_message: Optional[Message] = None, **kwargs) -> None: self.winner_count: int = winner_count self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count self.giveaway_message: Optional[Message] = giveaway_message @@ -8766,7 +8816,7 @@ def de_json(cls, json_string): def __init__(self, text: str, position: int, entities: Optional[List[MessageEntity]] = None, - is_manual: Optional[bool] = None) -> None: + is_manual: Optional[bool] = None, **kwargs) -> None: self.text: str = text self.entities: Optional[List[MessageEntity]] = entities self.position: Optional[int] = position @@ -8816,7 +8866,7 @@ def de_json(cls, json_string): def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, allow_sending_without_reply: Optional[bool] = None, quote: Optional[str] = None, quote_parse_mode: Optional[str] = None, quote_entities: Optional[List[MessageEntity]] = None, - quote_position: Optional[int] = None) -> None: + quote_position: Optional[int] = None, **kwargs) -> None: self.message_id: int = message_id self.chat_id: Optional[Union[int, str]] = chat_id self.allow_sending_without_reply: Optional[bool] = allow_sending_without_reply @@ -8876,7 +8926,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, request_id, user_ids): + def __init__(self, request_id, user_ids, **kwargs): self.request_id = request_id self.user_ids = user_ids @@ -8906,7 +8956,7 @@ def de_json(cls, json_string): obj['boost'] = ChatBoost.de_json(obj['boost']) return cls(**obj) - def __init__(self, chat, boost): + def __init__(self, chat, boost, **kwargs): self.chat = chat self.boost = boost @@ -8942,7 +8992,7 @@ def de_json(cls, json_string): obj['source'] = ChatBoostSource.de_json(obj['source']) return cls(**obj) - def __init__(self, chat, boost_id, remove_date, source): + def __init__(self, chat, boost_id, remove_date, source, **kwargs): self.chat = chat self.boost_id = boost_id self.remove_date = remove_date @@ -8969,10 +9019,11 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, source): + def __init__(self, source, **kwargs): self.source = source - + +# noinspection PyUnresolvedReferences class ChatBoostSourcePremium(ChatBoostSource): """ The boost was obtained by subscribing to Telegram Premium or by gifting a Telegram Premium subscription to another user. @@ -9000,8 +9051,9 @@ def de_json(cls, json_string): def __init__(self, user): super().__init__('premium') self.user = user - - + + +# noinspection PyUnresolvedReferences class ChatBoostSourceGiftCode(ChatBoostSource): """ The boost was obtained by the creation of Telegram Premium gift codes to boost a chat. @@ -9029,8 +9081,9 @@ def de_json(cls, json_string): def __init__(self, user): super().__init__('gift_code') self.user = user - - + + +# noinspection PyUnresolvedReferences class ChatBoostSourceGiveaway(ChatBoostSource): """ The boost was obtained by the creation of a Telegram Premium giveaway. @@ -9098,7 +9151,7 @@ def de_json(cls, json_string): obj['source'] = ChatBoostSource.de_json(obj['source']) return cls(**obj) - def __init__(self, boost_id, add_date, expiration_date, source): + def __init__(self, boost_id, add_date, expiration_date, source, **kwargs): self.boost_id = boost_id self.add_date = add_date self.expiration_date = expiration_date @@ -9126,7 +9179,7 @@ def de_json(cls, json_string): obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj['boosts']] return cls(**obj) - def __init__(self, boosts): + def __init__(self, boosts, **kwargs): self.boosts: ChatBoost = boosts @@ -9157,7 +9210,7 @@ def de_json(cls, json_string): obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) - def __init__(self, chat, message_id, date): + def __init__(self, chat, message_id, date, **kwargs): self.chat = chat self.message_id = message_id self.date = date From e2f53118630320c2f4167fd315e263a2bb50eeb1 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 23:17:20 +0300 Subject: [PATCH 103/480] Tune apihelper call parameters All non-necessary parameters of apihelper calls are used with named parameters to avoid call errors. --- telebot/__init__.py | 827 +++++++++++++++++++++++++++----------------- 1 file changed, 512 insertions(+), 315 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 3cbc6d7b1..13fdda5a2 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -440,8 +440,10 @@ def set_webhook(self, url: Optional[str]=None, certificate: Optional[Union[str, :rtype: :obj:`bool` if the request was successful. """ - return apihelper.set_webhook(self.token, url, certificate, max_connections, allowed_updates, ip_address, - drop_pending_updates, timeout, secret_token) + return apihelper.set_webhook( + self.token, url = url, certificate = certificate, max_connections = max_connections, + allowed_updates = allowed_updates, ip_address = ip_address, drop_pending_updates = drop_pending_updates, + timeout = timeout, secret_token = secret_token) def run_webhooks(self, @@ -566,7 +568,8 @@ def delete_webhook(self, drop_pending_updates: Optional[bool]=None, timeout: Opt :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.delete_webhook(self.token, drop_pending_updates, timeout) + return apihelper.delete_webhook( + self.token, drop_pending_updates=drop_pending_updates, timeout=timeout) def get_webhook_info(self, timeout: Optional[int]=None) -> types.WebhookInfo: @@ -582,8 +585,9 @@ def get_webhook_info(self, timeout: Optional[int]=None) -> types.WebhookInfo: :return: On success, returns a WebhookInfo object. :rtype: :class:`telebot.types.WebhookInfo` """ - result = apihelper.get_webhook_info(self.token, timeout) - return types.WebhookInfo.de_json(result) + return types.WebhookInfo.de_json( + apihelper.get_webhook_info(self.token, timeout=timeout) + ) def remove_webhook(self) -> bool: @@ -626,7 +630,9 @@ def get_updates(self, offset: Optional[int]=None, limit: Optional[int]=None, :return: An Array of Update objects is returned. :rtype: :obj:`list` of :class:`telebot.types.Update` """ - json_updates = apihelper.get_updates(self.token, offset, limit, timeout, allowed_updates, long_polling_timeout) + json_updates = apihelper.get_updates( + self.token, offset=offset, limit=limit, timeout=timeout, allowed_updates=allowed_updates, + long_polling_timeout=long_polling_timeout) return [types.Update.de_json(ju) for ju in json_updates] def __skip_updates(self): @@ -1071,7 +1077,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` - :param none_stop: Deprecated, use non_stop. Old typo, kept for backward compatibility. + :param none_stop: deprecated. :type none_stop: :obj:`bool` :param restart_on_change: Restart a file on file(s) change. Defaults to False @@ -1278,8 +1284,9 @@ def get_me(self) -> types.User: Telegram documentation: https://core.telegram.org/bots/api#getme """ - result = apihelper.get_me(self.token) - return types.User.de_json(result) + return types.User.de_json( + apihelper.get_me(self.token) + ) def get_file(self, file_id: Optional[str]) -> types.File: @@ -1297,7 +1304,9 @@ def get_file(self, file_id: Optional[str]) -> types.File: :return: :class:`telebot.types.File` """ - return types.File.de_json(apihelper.get_file(self.token, file_id)) + return types.File.de_json( + apihelper.get_file(self.token, file_id) + ) def get_file_url(self, file_id: Optional[str]) -> str: @@ -1378,7 +1387,8 @@ def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reacti :return: :obj:`bool` """ - return apihelper.set_message_reaction(self.token, chat_id, message_id, reaction, is_big) + return apihelper.set_message_reaction( + self.token, chat_id, message_id, reaction = reaction, is_big = is_big) def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, @@ -1402,8 +1412,9 @@ def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, :rtype: :class:`telebot.types.UserProfilePhotos` """ - result = apihelper.get_user_profile_photos(self.token, user_id, offset, limit) - return types.UserProfilePhotos.de_json(result) + return types.UserProfilePhotos.de_json( + apihelper.get_user_profile_photos(self.token, user_id, offset=offset, limit=limit) + ) def get_chat(self, chat_id: Union[int, str]) -> types.Chat: @@ -1419,8 +1430,9 @@ def get_chat(self, chat_id: Union[int, str]) -> types.Chat: :return: Chat information :rtype: :class:`telebot.types.Chat` """ - result = apihelper.get_chat(self.token, chat_id) - return types.Chat.de_json(result) + return types.Chat.de_json( + apihelper.get_chat(self.token, chat_id) + ) def leave_chat(self, chat_id: Union[int, str]) -> bool: @@ -1434,8 +1446,7 @@ def leave_chat(self, chat_id: Union[int, str]) -> bool: :return: :obj:`bool` """ - result = apihelper.leave_chat(self.token, chat_id) - return result + return apihelper.leave_chat(self.token, chat_id) def get_chat_administrators(self, chat_id: Union[int, str]) -> List[types.ChatMember]: @@ -1473,9 +1484,9 @@ def get_chat_members_count(self, chat_id: Union[int, str]) -> int: :return: Number of members in the chat. :rtype: :obj:`int` """ - result = apihelper.get_chat_member_count(self.token, chat_id) - return result - + return apihelper.get_chat_member_count(self.token, chat_id) + + def get_chat_member_count(self, chat_id: Union[int, str]) -> int: """ Use this method to get the number of members in a chat. @@ -1488,8 +1499,8 @@ def get_chat_member_count(self, chat_id: Union[int, str]) -> int: :return: Number of members in the chat. :rtype: :obj:`int` """ - result = apihelper.get_chat_member_count(self.token, chat_id) - return result + return apihelper.get_chat_member_count(self.token, chat_id) + def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str) -> types.StickerSet: """ @@ -1508,8 +1519,8 @@ def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str) :return: StickerSet object :rtype: :class:`telebot.types.StickerSet` """ - result = apihelper.set_chat_sticker_set(self.token, chat_id, sticker_set_name) - return result + return apihelper.set_chat_sticker_set(self.token, chat_id, sticker_set_name) + def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: """ @@ -1525,8 +1536,8 @@ def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: :return: Returns True on success. :rtype: :obj:`bool` """ - result = apihelper.delete_chat_sticker_set(self.token, chat_id) - return result + return apihelper.delete_chat_sticker_set(self.token, chat_id) + def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatMember: """ @@ -1543,8 +1554,10 @@ def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatM :return: Returns ChatMember object on success. :rtype: :class:`telebot.types.ChatMember` """ - result = apihelper.get_chat_member(self.token, chat_id, user_id) - return types.ChatMember.de_json(result) + return types.ChatMember.de_json( + apihelper.get_chat_member(self.token, chat_id, user_id) + ) + def send_message( self, chat_id: Union[int, str], text: str, @@ -1581,7 +1594,7 @@ def send_message( :param entities: List of special entities that appear in message text, which can be specified instead of parse_mode :type entities: Array of :class:`telebot.types.MessageEntity` - :param disable_web_page_preview: deprecated. Disables link previews for links in this message + :param disable_web_page_preview: deprecated. :type disable_web_page_preview: :obj:`bool` :param disable_notification: Sends the message silently. Users will receive a notification with no sound. @@ -1590,10 +1603,10 @@ def send_message( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -1620,15 +1633,12 @@ def send_message( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -1641,11 +1651,9 @@ def send_message( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if disable_web_page_preview is not None: - # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") if link_preview_options: - # show a conflict warning logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") else: # create a LinkPreviewOptions object @@ -1659,8 +1667,10 @@ def send_message( return types.Message.de_json( apihelper.send_message( self.token, chat_id, text, - reply_markup, parse_mode, disable_notification, timeout, - entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, link_preview_options=link_preview_options)) + reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, + timeout=timeout, entities=entities, protect_content=protect_content, message_thread_id=message_thread_id, + reply_parameters=reply_parameters, link_preview_options=link_preview_options)) + def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -1701,8 +1711,9 @@ def forward_message( protect_content = self.protect_content if (protect_content is None) else protect_content return types.Message.de_json( - apihelper.forward_message(self.token, chat_id, from_chat_id, message_id, disable_notification, timeout, protect_content, - message_thread_id)) + apihelper.forward_message( + self.token, chat_id, from_chat_id, message_id, disable_notification=disable_notification, + timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id)) def copy_message( @@ -1716,6 +1727,7 @@ def copy_message( protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID: @@ -1747,10 +1759,10 @@ def copy_message( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -1775,15 +1787,12 @@ def copy_message( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -1796,9 +1805,11 @@ def copy_message( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.MessageID.de_json( - apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, - disable_notification, reply_markup, - timeout, protect_content, message_thread_id, reply_parameters)) + apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption=caption, + parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, + reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters)) + def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -1827,7 +1838,8 @@ def delete_message(self, chat_id: Union[int, str], message_id: int, :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.delete_message(self.token, chat_id, message_id, timeout) + return apihelper.delete_message(self.token, chat_id, message_id, timeout=timeout) + def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ @@ -1848,6 +1860,7 @@ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ return apihelper.delete_messages(self.token, chat_id, message_ids) + def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: @@ -1879,8 +1892,12 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - return [types.MessageID.de_json(message_id) for message_id in - apihelper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id)] + result = apihelper.forward_messages( + self.token, chat_id, from_chat_id, message_ids, + disable_notification=disable_notification, message_thread_id=message_thread_id, + protect_content=protect_content) + return [types.MessageID.de_json(message_id) for message_id in result] + def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, @@ -1915,9 +1932,10 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], disable_notification = self.disable_notification if disable_notification is None else disable_notification protect_content = self.protect_content if protect_content is None else protect_content - return [types.MessageID.de_json(message_id) for message_id in - apihelper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, - protect_content, message_thread_id, remove_caption)] + result = apihelper.copy_messages( + self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, + message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) + return [types.MessageID.de_json(message_id) for message_id in result] def send_dice( @@ -1950,10 +1968,10 @@ def send_dice( :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -1975,15 +1993,12 @@ def send_dice( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -1997,8 +2012,9 @@ def send_dice( return types.Message.de_json( apihelper.send_dice( - self.token, chat_id, emoji, disable_notification, - reply_markup, timeout, protect_content, message_thread_id, reply_parameters) + self.token, chat_id, emoji=emoji, disable_notification=disable_notification, + reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters) ) @@ -2043,10 +2059,10 @@ def send_photo( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions @@ -2074,15 +2090,12 @@ def send_photo( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2096,11 +2109,13 @@ def send_photo( return types.Message.de_json( apihelper.send_photo( - self.token, chat_id, photo, caption, reply_markup, - parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, has_spoiler, reply_parameters)) + self.token, chat_id, photo, caption=caption, reply_markup=reply_markup, + parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, + caption_entities=caption_entities, protect_content=protect_content, + message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters) + ) + - # TODO: Rewrite this method like in API. def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], caption: Optional[str]=None, duration: Optional[int]=None, @@ -2156,10 +2171,10 @@ def send_audio( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -2180,7 +2195,7 @@ def send_audio( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` - :param thumb: Deprecated. Use thumbnail instead + :param thumb: deprecated. :type thumb: :obj:`str` or :class:`telebot.types.InputFile` :param reply_parameters: Reply parameters. @@ -2194,15 +2209,12 @@ def send_audio( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2215,16 +2227,18 @@ def send_audio( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumb is not None and thumbnail is None: - thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + thumbnail = thumb return types.Message.de_json( apihelper.send_audio( - self.token, chat_id, audio, caption, duration, performer, title, - reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, protect_content, message_thread_id, reply_parameters)) + self.token, chat_id, audio, caption=caption, duration=duration, performer=performer, title=title, + reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, + timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) + - # TODO: Rewrite this method like in API. def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], caption: Optional[str]=None, duration: Optional[int]=None, @@ -2269,10 +2283,10 @@ def send_voice( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -2297,15 +2311,12 @@ def send_voice( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2319,11 +2330,13 @@ def send_voice( return types.Message.de_json( apihelper.send_voice( - self.token, chat_id, voice, caption, duration, reply_markup, - parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, reply_parameters)) + self.token, chat_id, voice, caption=caption, duration=duration, reply_markup=reply_markup, + parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, + caption_entities=caption_entities, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) + - # TODO: Rewrite this method like in API. def send_document( self, chat_id: Union[int, str], document: Union[Any, str], caption: Optional[str]=None, @@ -2367,10 +2380,10 @@ def send_document( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -2397,7 +2410,7 @@ def send_document( :param message_thread_id: The thread to which the message will be sent :type message_thread_id: :obj:`int` - :param thumb: Deprecated. Use thumbnail instead + :param thumb: deprecated. :type thumb: :obj:`str` or :class:`telebot.types.InputFile` :param reply_parameters: Reply parameters. @@ -2411,15 +2424,12 @@ def send_document( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2432,24 +2442,23 @@ def send_document( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if data and (not document): - # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "document" instead.') document = data if thumb is not None and thumbnail is None: - thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + thumbnail = thumb return types.Message.de_json( apihelper.send_data( self.token, chat_id, document, 'document', - reply_parameters=reply_parameters, reply_markup = reply_markup, parse_mode = parse_mode, - disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, - caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, - visible_file_name = visible_file_name, protect_content = protect_content, message_thread_id = message_thread_id)) + reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, + timeout=timeout, caption=caption, thumbnail=thumbnail, caption_entities=caption_entities, + disable_content_type_detection=disable_content_type_detection, visible_file_name=visible_file_name, + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) - # TODO: Rewrite this method like in API. def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], @@ -2484,10 +2493,10 @@ def send_sticker( :param disable_notification: to disable the notification :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -2515,15 +2524,12 @@ def send_sticker( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2536,16 +2542,17 @@ def send_sticker( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if data and (not sticker): - # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data return types.Message.de_json( apihelper.send_data( - self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup, - disable_notification=disable_notification, timeout=timeout, + self.token, chat_id, sticker, 'sticker', + reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, - reply_parameters=reply_parameters)) + reply_parameters=reply_parameters) + ) + def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -2609,10 +2616,10 @@ def send_video( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -2632,7 +2639,7 @@ def send_video( :param has_spoiler: Pass True, if the video should be sent as a spoiler :type has_spoiler: :obj:`bool` - :param thumb: Deprecated. Use thumbnail instead + :param thumb: deprecated. :type thumb: :obj:`str` or :class:`telebot.types.InputFile` :param reply_parameters: Reply parameters @@ -2646,15 +2653,12 @@ def send_video( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2667,19 +2671,23 @@ def send_video( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if data and (not video): - # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "video" instead.') video = data if thumb is not None and thumbnail is None: - thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + thumbnail = thumb return types.Message.de_json( apihelper.send_video( - self.token, chat_id, video, duration, caption, reply_markup, - parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, - caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters)) + self.token, chat_id, video, + duration=duration, caption=caption, reply_markup=reply_markup, parse_mode=parse_mode, + supports_streaming=supports_streaming, disable_notification=disable_notification, timeout=timeout, + thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, + protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, + reply_parameters=reply_parameters) + ) + def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -2737,10 +2745,10 @@ def send_animation( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -2763,7 +2771,7 @@ def send_animation( :param has_spoiler: Pass True, if the animation should be sent as a spoiler :type has_spoiler: :obj:`bool` - :param thumb: Deprecated. Use thumbnail instead + :param thumb: deprecated. :type thumb: :obj:`str` or :class:`telebot.types.InputFile` :param reply_parameters: Reply parameters. @@ -2777,15 +2785,12 @@ def send_animation( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2798,15 +2803,19 @@ def send_animation( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumbnail is None and thumb is not None: - thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + thumbnail = thumb + return types.Message.de_json( apihelper.send_animation( - self.token, chat_id, animation, duration, caption, - reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, protect_content, width, height, message_thread_id, has_spoiler, reply_parameters)) + self.token, chat_id, animation, duration=duration, caption=caption, reply_markup=reply_markup, + parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, + thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, + width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, + has_spoiler=has_spoiler) + ) + - # TODO: Rewrite this method like in API. def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], duration: Optional[int]=None, @@ -2848,10 +2857,10 @@ def send_video_note( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -2869,7 +2878,7 @@ def send_video_note( :param message_thread_id: Identifier of a message thread, in which the video note will be sent :type message_thread_id: :obj:`int` - :param thumb: Deprecated. Use thumbnail instead + :param thumb: deprecated. :type thumb: :obj:`str` or :class:`telebot.types.InputFile` :param reply_parameters: Reply parameters. @@ -2882,15 +2891,12 @@ def send_video_note( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2903,13 +2909,15 @@ def send_video_note( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumbnail is None and thumb is not None: - thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') + thumbnail = thumb return types.Message.de_json( apihelper.send_video_note( - self.token, chat_id, data, duration, length, reply_markup, - disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters)) + self.token, chat_id, data, duration=duration, length=length, reply_markup=reply_markup, + disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) def send_media_group( @@ -2942,10 +2950,10 @@ def send_media_group( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -2964,15 +2972,12 @@ def send_media_group( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -2985,11 +2990,11 @@ def send_media_group( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = apihelper.send_media_group( - self.token, chat_id, media, disable_notification, timeout, - protect_content, message_thread_id, reply_parameters) + self.token, chat_id, media, disable_notification=disable_notification, timeout=timeout, + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) return [types.Message.de_json(msg) for msg in result] - # TODO: Rewrite this method like in API. + def send_location( self, chat_id: Union[int, str], latitude: float, longitude: float, @@ -3030,10 +3035,10 @@ def send_location( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param timeout: Timeout in seconds for the request. @@ -3064,15 +3069,12 @@ def send_location( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -3086,10 +3088,12 @@ def send_location( return types.Message.de_json( apihelper.send_location( - self.token, chat_id, latitude, longitude, live_period, - reply_markup, disable_notification, timeout, - horizontal_accuracy, heading, proximity_alert_radius, - protect_content, message_thread_id, reply_parameters)) + self.token, chat_id, latitude, longitude, live_period=live_period, reply_markup=reply_markup, + disable_notification=disable_notification, timeout=timeout, horizontal_accuracy=horizontal_accuracy, + heading=heading, proximity_alert_radius=proximity_alert_radius, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) + def edit_message_live_location( self, latitude: float, longitude: float, @@ -3144,9 +3148,11 @@ def edit_message_live_location( """ return types.Message.de_json( apihelper.edit_message_live_location( - self.token, latitude, longitude, chat_id, message_id, - inline_message_id, reply_markup, timeout, - horizontal_accuracy, heading, proximity_alert_radius)) + self.token, latitude, longitude, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, + reply_markup=reply_markup, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, + proximity_alert_radius=proximity_alert_radius) + ) + def stop_message_live_location( self, chat_id: Optional[Union[int, str]]=None, @@ -3181,9 +3187,11 @@ def stop_message_live_location( """ return types.Message.de_json( apihelper.stop_message_live_location( - self.token, chat_id, message_id, inline_message_id, reply_markup, timeout)) + self.token, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, + reply_markup=reply_markup, timeout=timeout) + ) + - # TODO: Rewrite this method like in API. def send_venue( self, chat_id: Union[int, str], latitude: Optional[float], longitude: Optional[float], @@ -3230,10 +3238,10 @@ def send_venue( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, @@ -3266,15 +3274,12 @@ def send_venue( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -3288,12 +3293,13 @@ def send_venue( return types.Message.de_json( apihelper.send_venue( - self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, - disable_notification, reply_markup, timeout, - google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters)) + self.token, chat_id, latitude, longitude, title, address, foursquare_id=foursquare_id, + foursquare_type=foursquare_type, disable_notification=disable_notification, reply_markup=reply_markup, + timeout=timeout, google_place_id=google_place_id, google_place_type=google_place_type, + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) - # TODO: Rewrite this method like in API. def send_contact( self, chat_id: Union[int, str], phone_number: str, first_name: str, last_name: Optional[str]=None, @@ -3328,10 +3334,10 @@ def send_contact( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: deprecated. If the message is a reply, ID of the original message + :param reply_to_message_id: deprecated. :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: deprecated. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, @@ -3358,15 +3364,12 @@ def send_contact( protect_content = self.protect_content if (protect_content is None) else protect_content if allow_sending_without_reply is not None: - # show a deprecation warning logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") if reply_to_message_id: - # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") if reply_parameters: - # show a conflict warning logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") else: # create a ReplyParameters object @@ -3380,9 +3383,11 @@ def send_contact( return types.Message.de_json( apihelper.send_contact( - self.token, chat_id, phone_number, first_name, last_name, vcard, - disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters)) + self.token, chat_id, phone_number, first_name, last_name=last_name, vcard=vcard, + disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) + def send_chat_action( self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None) -> bool: @@ -3414,7 +3419,9 @@ def send_chat_action( :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.send_chat_action(self.token, chat_id, action, timeout, message_thread_id) + return apihelper.send_chat_action( + self.token, chat_id, action, timeout=timeout, message_thread_id=message_thread_id) + @util.deprecated(deprecation_text="Use ban_chat_member instead") def kick_chat_member( @@ -3424,7 +3431,9 @@ def kick_chat_member( """ This function is deprecated. Use `ban_chat_member` instead. """ - return apihelper.ban_chat_member(self.token, chat_id, user_id, until_date, revoke_messages) + return apihelper.ban_chat_member( + self.token, chat_id, user_id, until_date=until_date, revoke_messages=revoke_messages) + def ban_chat_member( self, chat_id: Union[int, str], user_id: int, @@ -3457,7 +3466,9 @@ def ban_chat_member( :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.ban_chat_member(self.token, chat_id, user_id, until_date, revoke_messages) + return apihelper.ban_chat_member( + self.token, chat_id, user_id, until_date=until_date, revoke_messages=revoke_messages) + def unban_chat_member( self, chat_id: Union[int, str], user_id: int, @@ -3486,6 +3497,7 @@ def unban_chat_member( """ return apihelper.unban_chat_member(self.token, chat_id, user_id, only_if_banned) + def restrict_chat_member( self, chat_id: Union[int, str], user_id: int, until_date: Optional[Union[int, datetime]]=None, @@ -3562,7 +3574,6 @@ def restrict_chat_member( :return: True on success :rtype: :obj:`bool` """ - if permissions is None: permissions = types.ChatPermissions( can_send_messages=can_send_messages, @@ -3575,8 +3586,11 @@ def restrict_chat_member( can_pin_messages=can_pin_messages ) logger.warning('The parameters "can_..." are deprecated, use "permissions" instead.') + return apihelper.restrict_chat_member( - self.token, chat_id, user_id, permissions, until_date, use_independent_chat_permissions) + self.token, chat_id, user_id, permissions, until_date=until_date, + use_independent_chat_permissions=use_independent_chat_permissions) + def promote_chat_member( self, chat_id: Union[int, str], user_id: int, @@ -3674,11 +3688,15 @@ def promote_chat_member( can_manage_video_chats = can_manage_voice_chats return apihelper.promote_chat_member( - self.token, chat_id, user_id, can_change_info, can_post_messages, - can_edit_messages, can_delete_messages, can_invite_users, - can_restrict_members, can_pin_messages, can_promote_members, - is_anonymous, can_manage_chat, can_manage_video_chats, can_manage_topics, - can_post_stories, can_edit_stories, can_delete_stories) + self.token, chat_id, user_id, can_change_info=can_change_info, can_post_messages=can_post_messages, + can_edit_messages=can_edit_messages, can_delete_messages=can_delete_messages, + can_invite_users=can_invite_users, can_restrict_members=can_restrict_members, + can_pin_messages=can_pin_messages, can_promote_members=can_promote_members, + is_anonymous=is_anonymous, can_manage_chat=can_manage_chat, + can_manage_video_chats=can_manage_video_chats, can_manage_topics=can_manage_topics, + can_post_stories=can_post_stories, can_edit_stories=can_edit_stories, + can_delete_stories=can_delete_stories) + def set_chat_administrator_custom_title( self, chat_id: Union[int, str], user_id: int, custom_title: str) -> bool: @@ -3703,6 +3721,7 @@ def set_chat_administrator_custom_title( :rtype: :obj:`bool` """ return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title) + def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ @@ -3726,6 +3745,7 @@ def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[i """ return apihelper.ban_chat_sender_chat(self.token, chat_id, sender_chat_id) + def unban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ Use this method to unban a previously banned channel chat in a supergroup or channel. @@ -3746,6 +3766,7 @@ def unban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union """ return apihelper.unban_chat_sender_chat(self.token, chat_id, sender_chat_id) + def set_chat_permissions( self, chat_id: Union[int, str], permissions: types.ChatPermissions, use_independent_chat_permissions: Optional[bool]=None) -> bool: @@ -3772,7 +3793,9 @@ def set_chat_permissions( :return: True on success :rtype: :obj:`bool` """ - return apihelper.set_chat_permissions(self.token, chat_id, permissions, use_independent_chat_permissions) + return apihelper.set_chat_permissions( + self.token, chat_id, permissions, use_independent_chat_permissions=use_independent_chat_permissions) + def create_chat_invite_link( self, chat_id: Union[int, str], @@ -3811,6 +3834,7 @@ def create_chat_invite_link( apihelper.create_chat_invite_link(self.token, chat_id, name, expire_date, member_limit, creates_join_request) ) + def edit_chat_invite_link( self, chat_id: Union[int, str], invite_link: Optional[str] = None, @@ -3850,6 +3874,7 @@ def edit_chat_invite_link( apihelper.edit_chat_invite_link(self.token, chat_id, invite_link, name, expire_date, member_limit, creates_join_request) ) + def revoke_chat_invite_link( self, chat_id: Union[int, str], invite_link: str) -> types.ChatInviteLink: """ @@ -3873,6 +3898,7 @@ def revoke_chat_invite_link( apihelper.revoke_chat_invite_link(self.token, chat_id, invite_link) ) + def export_chat_invite_link(self, chat_id: Union[int, str]) -> str: """ Use this method to export an invite link to a supergroup or a channel. The bot must be an administrator @@ -3889,6 +3915,7 @@ def export_chat_invite_link(self, chat_id: Union[int, str]) -> str: """ return apihelper.export_chat_invite_link(self.token, chat_id) + def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ Use this method to approve a chat join request. @@ -3909,6 +3936,7 @@ def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int """ return apihelper.approve_chat_join_request(self.token, chat_id, user_id) + def decline_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ Use this method to decline a chat join request. @@ -3929,6 +3957,7 @@ def decline_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int """ return apihelper.decline_chat_join_request(self.token, chat_id, user_id) + def set_chat_photo(self, chat_id: Union[int, str], photo: Any) -> bool: """ Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. @@ -3950,6 +3979,7 @@ def set_chat_photo(self, chat_id: Union[int, str], photo: Any) -> bool: """ return apihelper.set_chat_photo(self.token, chat_id, photo) + def delete_chat_photo(self, chat_id: Union[int, str]) -> bool: """ Use this method to delete a chat photo. Photos can't be changed for private chats. @@ -3967,6 +3997,7 @@ def delete_chat_photo(self, chat_id: Union[int, str]) -> bool: :rtype: :obj:`bool` """ return apihelper.delete_chat_photo(self.token, chat_id) + def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> List[types.BotCommand]: @@ -3988,9 +4019,10 @@ def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, :return: List of BotCommand on success. :rtype: :obj:`list` of :class:`telebot.types.BotCommand` """ - result = apihelper.get_my_commands(self.token, scope, language_code) + result = apihelper.get_my_commands(self.token, scope=scope, language_code=language_code) return [types.BotCommand.de_json(cmd) for cmd in result] + def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=None): """ Use this method to change the bot's name. Returns True on success. @@ -4006,8 +4038,8 @@ def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=Non :return: True on success. """ + return apihelper.set_my_name(self.token, name=name, language_code=language_code) - return apihelper.set_my_name(self.token, name, language_code) def get_my_name(self, language_code: Optional[str]=None): """ @@ -4021,10 +4053,11 @@ def get_my_name(self, language_code: Optional[str]=None): :return: :class:`telebot.types.BotName` """ + return types.BotName.de_json( + apihelper.get_my_name(self.token, language_code=language_code) + ) + - result = apihelper.get_my_name(self.token, language_code) - return types.BotName.de_json(result) - def set_my_description(self, description: Optional[str]=None, language_code: Optional[str]=None): """ Use this method to change the bot's description, which is shown in @@ -4043,7 +4076,9 @@ def set_my_description(self, description: Optional[str]=None, language_code: Opt :return: True on success. """ - return apihelper.set_my_description(self.token, description, language_code) + return apihelper.set_my_description( + self.token, description=description, language_code=language_code) + def get_my_description(self, language_code: Optional[str]=None): """ @@ -4057,8 +4092,9 @@ def get_my_description(self, language_code: Optional[str]=None): :return: :class:`telebot.types.BotDescription` """ - - return types.BotDescription.de_json(apihelper.get_my_description(self.token, language_code)) + return types.BotDescription.de_json( + apihelper.get_my_description(self.token, language_code=language_code)) + def set_my_short_description(self, short_description:Optional[str]=None, language_code:Optional[str]=None): """ @@ -4077,8 +4113,9 @@ def set_my_short_description(self, short_description:Optional[str]=None, languag :return: True on success. """ + return apihelper.set_my_short_description( + self.token, short_description=short_description, language_code=language_code) - return apihelper.set_my_short_description(self.token, short_description, language_code) def get_my_short_description(self, language_code: Optional[str]=None): """ @@ -4092,11 +4129,11 @@ def get_my_short_description(self, language_code: Optional[str]=None): :return: :class:`telebot.types.BotShortDescription` """ - - return types.BotShortDescription.de_json(apihelper.get_my_short_description(self.token, language_code)) + return types.BotShortDescription.de_json( + apihelper.get_my_short_description(self.token, language_code=language_code)) + - def set_chat_menu_button(self, chat_id: Union[int, str]=None, - menu_button: types.MenuButton=None) -> bool: + def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ Use this method to change the bot's menu button in a private chat, or the default menu button. @@ -4114,7 +4151,8 @@ def set_chat_menu_button(self, chat_id: Union[int, str]=None, :return: True on success. :rtype: :obj:`bool` """ - return apihelper.set_chat_menu_button(self.token, chat_id, menu_button) + return apihelper.set_chat_menu_button(self.token, chat_id=chat_id, menu_button=menu_button) + def get_chat_menu_button(self, chat_id: Union[int, str]=None) -> types.MenuButton: """ @@ -4131,7 +4169,9 @@ def get_chat_menu_button(self, chat_id: Union[int, str]=None) -> types.MenuButto :return: types.MenuButton :rtype: :class:`telebot.types.MenuButton` """ - return types.MenuButton.de_json(apihelper.get_chat_menu_button(self.token, chat_id)) + return types.MenuButton.de_json( + apihelper.get_chat_menu_button(self.token, chat_id=chat_id)) + def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, for_channels: Optional[bool]=None) -> bool: @@ -4155,7 +4195,8 @@ def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRig :return: True on success. :rtype: :obj:`bool` """ - return apihelper.set_my_default_administrator_rights(self.token, rights, for_channels) + return apihelper.set_my_default_administrator_rights(self.token, rights=rights, for_channels=for_channels) + def get_my_default_administrator_rights(self, for_channels: Optional[bool]=None) -> types.ChatAdministratorRights: """ @@ -4170,7 +4211,10 @@ def get_my_default_administrator_rights(self, for_channels: Optional[bool]=None) :return: Returns ChatAdministratorRights on success. :rtype: :class:`telebot.types.ChatAdministratorRights` """ - return types.ChatAdministratorRights.de_json(apihelper.get_my_default_administrator_rights(self.token, for_channels)) + return types.ChatAdministratorRights.de_json( + apihelper.get_my_default_administrator_rights(self.token, for_channels=for_channels) + ) + def set_my_commands(self, commands: List[types.BotCommand], scope: Optional[types.BotCommandScope]=None, @@ -4195,7 +4239,8 @@ def set_my_commands(self, commands: List[types.BotCommand], :return: True on success. :rtype: :obj:`bool` """ - return apihelper.set_my_commands(self.token, commands, scope, language_code) + return apihelper.set_my_commands(self.token, commands, scope=scope, language_code=language_code) + def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> bool: @@ -4218,7 +4263,8 @@ def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, :return: True on success. :rtype: :obj:`bool` """ - return apihelper.delete_my_commands(self.token, scope, language_code) + return apihelper.delete_my_commands(self.token, scope=scope, language_code=language_code) + def set_chat_title(self, chat_id: Union[int, str], title: str) -> bool: """ @@ -4242,6 +4288,7 @@ def set_chat_title(self, chat_id: Union[int, str], title: str) -> bool: """ return apihelper.set_chat_title(self.token, chat_id, title) + def set_chat_description(self, chat_id: Union[int, str], description: Optional[str]=None) -> bool: """ Use this method to change the description of a supergroup or a channel. @@ -4261,6 +4308,7 @@ def set_chat_description(self, chat_id: Union[int, str], description: Optional[s """ return apihelper.set_chat_description(self.token, chat_id, description) + def pin_chat_message( self, chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=False) -> bool: @@ -4287,7 +4335,8 @@ def pin_chat_message( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification - return apihelper.pin_chat_message(self.token, chat_id, message_id, disable_notification) + return apihelper.pin_chat_message(self.token, chat_id, message_id, disable_notification=disable_notification) + def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int]=None) -> bool: """ @@ -4309,6 +4358,7 @@ def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int] """ return apihelper.unpin_chat_message(self.token, chat_id, message_id) + def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: """ Use this method to unpin a all pinned messages in a supergroup chat. @@ -4326,6 +4376,7 @@ def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: """ return apihelper.unpin_all_chat_messages(self.token, chat_id) + def edit_message_text( self, text: str, chat_id: Optional[Union[int, str]]=None, @@ -4389,12 +4440,15 @@ def edit_message_text( if link_preview_options and (link_preview_options.disable_web_page_preview is None): link_preview_options.disable_web_page_preview = self.disable_web_page_preview - result = apihelper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, - entities, reply_markup, link_preview_options) + result = apihelper.edit_message_text( + self.token, text, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, + parse_mode=parse_mode, entities=entities, reply_markup=reply_markup, link_preview_options=link_preview_options) + if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) + def edit_message_media( self, media: Any, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, @@ -4425,11 +4479,15 @@ def edit_message_media( :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = apihelper.edit_message_media(self.token, media, chat_id, message_id, inline_message_id, reply_markup) + result = apihelper.edit_message_media( + self.token, media, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, + reply_markup=reply_markup) + if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) + def edit_message_reply_markup( self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, @@ -4455,11 +4513,15 @@ def edit_message_reply_markup( :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = apihelper.edit_message_reply_markup(self.token, chat_id, message_id, inline_message_id, reply_markup) + result = apihelper.edit_message_reply_markup( + self.token, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, + reply_markup=reply_markup) + if type(result) == bool: return result return types.Message.de_json(result) + def send_game( self, chat_id: Union[int, str], game_short_name: str, disable_notification: Optional[bool]=None, @@ -4532,11 +4594,13 @@ def send_game( if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply - result = apihelper.send_game( - self.token, chat_id, game_short_name, disable_notification, - reply_markup, timeout, - protect_content, message_thread_id, reply_parameters) - return types.Message.de_json(result) + return types.Message.de_json( + apihelper.send_game( + self.token, chat_id, game_short_name, disable_notification=disable_notification, + reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters) + ) + def set_game_score( self, user_id: Union[int, str], score: int, @@ -4574,12 +4638,15 @@ def set_game_score( :return: On success, if the message was sent by the bot, returns the edited Message, otherwise returns True. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = apihelper.set_game_score(self.token, user_id, score, force, disable_edit_message, chat_id, - message_id, inline_message_id) + result = apihelper.set_game_score( + self.token, user_id, score, force=force, disable_edit_message=disable_edit_message, + chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id) + if type(result) == bool: return result return types.Message.de_json(result) + def get_game_high_scores( self, user_id: int, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, @@ -4609,10 +4676,11 @@ def get_game_high_scores( :return: On success, returns an Array of GameHighScore objects. :rtype: List[types.GameHighScore] """ - result = apihelper.get_game_high_scores(self.token, user_id, chat_id, message_id, inline_message_id) + result = apihelper.get_game_high_scores( + self.token, user_id, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id) return [types.GameHighScore.de_json(r) for r in result] - # TODO: rewrite this method like in API + def send_invoice( self, chat_id: Union[int, str], title: str, description: str, invoice_payload: str, provider_token: str, currency: str, @@ -4766,14 +4834,19 @@ def send_invoice( if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply - result = apihelper.send_invoice( - self.token, chat_id, title, description, invoice_payload, provider_token, - currency, prices, start_parameter, photo_url, photo_size, photo_width, - photo_height, need_name, need_phone_number, need_email, need_shipping_address, - send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification, - reply_markup, provider_data, timeout, - max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters) - return types.Message.de_json(result) + return types.Message.de_json( + apihelper.send_invoice( + self.token, chat_id, title, description, invoice_payload, provider_token, + currency, prices, start_parameter=start_parameter, photo_url=photo_url, + photo_size=photo_size, photo_width=photo_width, photo_height=photo_height, + need_name=need_name, need_phone_number=need_phone_number, need_email=need_email, + need_shipping_address=need_shipping_address, send_phone_number_to_provider=send_phone_number_to_provider, + send_email_to_provider=send_email_to_provider, is_flexible=is_flexible, + disable_notification=disable_notification, reply_markup=reply_markup, + provider_data=provider_data, timeout=timeout, protect_content=protect_content, + message_thread_id=message_thread_id, reply_parameters=reply_parameters, + max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts) + ) def create_invoice_link(self, title: str, description: str, payload:str, provider_token: str, @@ -4870,16 +4943,17 @@ def create_invoice_link(self, :return: Created invoice link as String on success. :rtype: :obj:`str` """ - result = apihelper.create_invoice_link( + return apihelper.create_invoice_link( self.token, title, description, payload, provider_token, - currency, prices, max_tip_amount, suggested_tip_amounts, provider_data, - photo_url, photo_size, photo_width, photo_height, need_name, need_phone_number, - need_email, need_shipping_address, send_phone_number_to_provider, - send_email_to_provider, is_flexible) - return result + currency, prices, max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts, + provider_data=provider_data, photo_url=photo_url, photo_size=photo_size, + photo_width=photo_width, photo_height=photo_height, need_name=need_name, + need_phone_number=need_phone_number, need_email=need_email, + need_shipping_address=need_shipping_address, send_phone_number_to_provider=send_phone_number_to_provider, + send_email_to_provider=send_email_to_provider, is_flexible=is_flexible) + # noinspection PyShadowingBuiltins - # TODO: rewrite this method like in API def send_poll( self, chat_id: Union[int, str], question: str, options: List[str], is_anonymous: Optional[bool]=None, type: Optional[str]=None, @@ -5006,12 +5080,16 @@ def send_poll( return types.Message.de_json( apihelper.send_poll( - self.token, chat_id, - question, options, - is_anonymous, type, allows_multiple_answers, correct_option_id, - explanation, explanation_parse_mode, open_period, close_date, is_closed, - disable_notification,reply_markup, timeout, explanation_entities, protect_content, message_thread_id, - reply_parameters)) + self.token, chat_id, question, options, + is_anonymous=is_anonymous, type=type, allows_multiple_answers=allows_multiple_answers, + correct_option_id=correct_option_id, explanation=explanation, + explanation_parse_mode=explanation_parse_mode, open_period=open_period, + close_date=close_date, is_closed=is_closed, disable_notification=disable_notification, + reply_markup=reply_markup, timeout=timeout, explanation_entities=explanation_entities, + protect_content=protect_content, message_thread_id=message_thread_id, + reply_parameters=reply_parameters) + ) + def stop_poll( self, chat_id: Union[int, str], message_id: int, @@ -5033,7 +5111,10 @@ def stop_poll( :return: On success, the stopped Poll is returned. :rtype: :obj:`types.Poll` """ - return types.Poll.de_json(apihelper.stop_poll(self.token, chat_id, message_id, reply_markup)) + return types.Poll.de_json( + apihelper.stop_poll(self.token, chat_id, message_id, reply_markup=reply_markup) + ) + def answer_shipping_query( self, shipping_query_id: str, ok: bool, @@ -5060,7 +5141,9 @@ def answer_shipping_query( :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.answer_shipping_query(self.token, shipping_query_id, ok, shipping_options, error_message) + return apihelper.answer_shipping_query( + self.token, shipping_query_id, ok, shipping_options=shipping_options, error_message=error_message) + def answer_pre_checkout_query( self, pre_checkout_query_id: int, ok: bool, @@ -5089,7 +5172,9 @@ def answer_pre_checkout_query( :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.answer_pre_checkout_query(self.token, pre_checkout_query_id, ok, error_message) + return apihelper.answer_pre_checkout_query( + self.token, pre_checkout_query_id, ok, error_message=error_message) + def edit_message_caption( self, caption: str, chat_id: Optional[Union[int, str]]=None, @@ -5129,12 +5214,15 @@ def edit_message_caption( """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode - result = apihelper.edit_message_caption(self.token, caption, chat_id, message_id, inline_message_id, - parse_mode, caption_entities, reply_markup) + result = apihelper.edit_message_caption( + self.token, caption, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, + parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup) + if type(result) == bool: return result return types.Message.de_json(result) + def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message: """ Convenience function for `send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs)` @@ -5152,6 +5240,7 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message """ return self.send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs) + def answer_inline_query( self, inline_query_id: str, results: List[Any], @@ -5206,8 +5295,10 @@ def answer_inline_query( logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.") button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter) - return apihelper.answer_inline_query(self.token, inline_query_id, results, cache_time, is_personal, next_offset, - button) + return apihelper.answer_inline_query( + self.token, inline_query_id, results, cache_time=cache_time, is_personal=is_personal, + next_offset=next_offset, button=button) + def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bool: """ @@ -5224,9 +5315,9 @@ def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bo :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.unpin_all_general_forum_topic_messages(self.token, chat_id) + def answer_callback_query( self, callback_query_id: int, text: Optional[str]=None, show_alert: Optional[bool]=None, @@ -5256,7 +5347,9 @@ def answer_callback_query( :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.answer_callback_query(self.token, callback_query_id, text, show_alert, url, cache_time) + return apihelper.answer_callback_query( + self.token, callback_query_id, text=text, show_alert=show_alert, url=url, cache_time=cache_time) + def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts: """ @@ -5273,9 +5366,10 @@ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types. :return: On success, a UserChatBoosts object is returned. :rtype: :class:`telebot.types.UserChatBoosts` """ + return types.UserChatBoosts.de_json( + apihelper.get_user_chat_boosts(self.token, chat_id, user_id) + ) - result = apihelper.get_user_chat_boosts(self.token, chat_id, user_id) - return types.UserChatBoosts.de_json(result) def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None): """ @@ -5296,8 +5390,8 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[An :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail) + @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]=None): @@ -5320,7 +5414,8 @@ def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]= :rtype: :obj:`bool` """ # deprecated - return self.set_sticker_set_thumbnail(name, user_id, thumb) + return self.set_sticker_set_thumbnail(name, user_id, thumbnail=thumb) + def get_sticker_set(self, name: str) -> types.StickerSet: """ @@ -5334,8 +5429,9 @@ def get_sticker_set(self, name: str) -> types.StickerSet: :return: On success, a StickerSet object is returned. :rtype: :class:`telebot.types.StickerSet` """ - result = apihelper.get_sticker_set(self.token, name) - return types.StickerSet.de_json(result) + return types.StickerSet.de_json( + apihelper.get_sticker_set(self.token, name) + ) def get_custom_emoji_stickers(self, custom_emoji_ids: List[str]) -> List[types.Sticker]: """ @@ -5350,6 +5446,7 @@ def get_custom_emoji_stickers(self, custom_emoji_ids: List[str]) -> List[types.S """ result = apihelper.get_custom_emoji_stickers(self.token, custom_emoji_ids) return [types.Sticker.de_json(sticker) for sticker in result] + def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: """ @@ -5366,7 +5463,8 @@ def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.set_sticker_keywords(self.token, sticker, keywords) + return apihelper.set_sticker_keywords(self.token, sticker, keywords=keywords) + def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosition=None) -> bool: """ @@ -5383,7 +5481,7 @@ def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosit :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.set_sticker_mask_position(self.token, sticker, mask_position) + return apihelper.set_sticker_mask_position(self.token, sticker, mask_position=mask_position) def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Optional[str]=None) -> bool: @@ -5400,7 +5498,8 @@ def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Opt :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.set_custom_emoji_sticker_set_thumbnail(self.token, name, custom_emoji_id) + return apihelper.set_custom_emoji_sticker_set_thumbnail(self.token, name, custom_emoji_id=custom_emoji_id) + def set_sticker_set_title(self, name: str, title: str) -> bool: """ @@ -5416,8 +5515,8 @@ def set_sticker_set_title(self, name: str, title: str) -> bool: :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.set_sticker_set_title(self.token, name, title) + def delete_sticker_set(self, name:str) -> bool: """ @@ -5429,8 +5528,8 @@ def delete_sticker_set(self, name:str) -> bool: :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.delete_sticker_set(self.token, name) + def set_sticker_emoji_list(self, sticker: str, emoji_list: List[str]) -> bool: """ @@ -5446,7 +5545,6 @@ def set_sticker_emoji_list(self, sticker: str, emoji_list: List[str]) -> bool: :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.set_sticker_emoji_list(self.token, sticker, emoji_list) @@ -5479,8 +5577,10 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s sticker = png_sticker sticker_format = "static" - result = apihelper.upload_sticker_file(self.token, user_id, sticker, sticker_format) - return types.File.de_json(result) + return types.File.de_json( + apihelper.upload_sticker_file(self.token, user_id, sticker, sticker_format) + ) + def create_new_sticker_set( self, user_id: int, name: str, title: str, @@ -5570,11 +5670,10 @@ def create_new_sticker_set( if stickers is None: raise ValueError('You must pass at least one sticker') stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] - - return apihelper.create_new_sticker_set( - self.token, user_id, name, title, stickers, sticker_format, sticker_type, needs_repainting) + self.token, user_id, name, title, stickers, sticker_format, sticker_type=sticker_type, + needs_repainting=needs_repainting) def add_sticker_to_set( @@ -5638,8 +5737,8 @@ def add_sticker_to_set( raise ValueError('You must pass at least one sticker.') sticker = types.InputSticker(old_sticker, emojis, mask_position) - return apihelper.add_sticker_to_set( - self.token, user_id, name, sticker) + return apihelper.add_sticker_to_set(self.token, user_id, name, sticker) + def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: """ @@ -5658,6 +5757,7 @@ def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: """ return apihelper.set_sticker_position_in_set(self.token, sticker, position) + def delete_sticker_from_set(self, sticker: str) -> bool: """ Use this method to delete a sticker from a set created by the bot. Returns True on success. @@ -5670,6 +5770,7 @@ def delete_sticker_from_set(self, sticker: str) -> bool: """ return apihelper.delete_sticker_from_set(self.token, sticker) + def create_forum_topic(self, chat_id: int, name: str, icon_color: Optional[int]=None, icon_custom_emoji_id: Optional[str]=None) -> types.ForumTopic: @@ -5696,9 +5797,11 @@ def create_forum_topic(self, :rtype: :class:`telebot.types.ForumTopic` """ return types.ForumTopic.de_json( - apihelper.create_forum_topic(self.token, chat_id, name, icon_color, icon_custom_emoji_id) + apihelper.create_forum_topic( + self.token, chat_id, name, icon_color=icon_color, icon_custom_emoji_id=icon_custom_emoji_id) ) + def edit_forum_topic( self, chat_id: Union[int, str], message_thread_id: int, name: Optional[str]=None, @@ -5729,7 +5832,9 @@ def edit_forum_topic( :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.edit_forum_topic(self.token, chat_id, message_thread_id, name, icon_custom_emoji_id) + return apihelper.edit_forum_topic( + self.token, chat_id, message_thread_id, name=name, icon_custom_emoji_id=icon_custom_emoji_id) + def close_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) -> bool: """ @@ -5739,7 +5844,7 @@ def close_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) -> Telegram documentation: https://core.telegram.org/bots/api#closeforumtopic - :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :aram chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` :param message_thread_id: Identifier of the topic to close @@ -5750,6 +5855,7 @@ def close_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) -> """ return apihelper.close_forum_topic(self.token, chat_id, message_thread_id) + def reopen_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) -> bool: """ Use this method to reopen a closed topic in a forum supergroup chat. The bot must be an administrator in the chat @@ -5769,6 +5875,7 @@ def reopen_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) - """ return apihelper.reopen_forum_topic(self.token, chat_id, message_thread_id) + def delete_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) -> bool: """ Use this method to delete a topic in a forum supergroup chat. The bot must be an administrator in the chat for this @@ -5788,6 +5895,7 @@ def delete_forum_topic(self, chat_id: Union[str, int], message_thread_id: int) - """ return apihelper.delete_forum_topic(self.token, chat_id, message_thread_id) + def unpin_all_forum_topic_messages(self, chat_id: Union[str, int], message_thread_id: int) -> bool: """ Use this method to clear the list of pinned messages in a forum topic. The bot must be an administrator in the @@ -5807,6 +5915,7 @@ def unpin_all_forum_topic_messages(self, chat_id: Union[str, int], message_threa """ return apihelper.unpin_all_forum_topic_messages(self.token, chat_id, message_thread_id) + def edit_general_forum_topic(self, chat_id: Union[int, str], name: str) -> bool: """ Use this method to edit the name of the 'General' topic in a forum supergroup chat. @@ -5821,9 +5930,9 @@ def edit_general_forum_topic(self, chat_id: Union[int, str], name: str) -> bool: :param name: New topic name, 1-128 characters :type name: :obj:`str` """ - return apihelper.edit_general_forum_topic(self.token, chat_id, name) + def close_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ Use this method to close the 'General' topic in a forum supergroup chat. @@ -5837,6 +5946,7 @@ def close_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ return apihelper.close_general_forum_topic(self.token, chat_id) + def reopen_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ Use this method to reopen the 'General' topic in a forum supergroup chat. @@ -5850,6 +5960,7 @@ def reopen_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ return apihelper.reopen_general_forum_topic(self.token, chat_id) + def hide_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ Use this method to hide the 'General' topic in a forum supergroup chat. @@ -5863,6 +5974,7 @@ def hide_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ return apihelper.hide_general_forum_topic(self.token, chat_id) + def unhide_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ Use this method to unhide the 'General' topic in a forum supergroup chat. @@ -5876,6 +5988,7 @@ def unhide_general_forum_topic(self, chat_id: Union[int, str]) -> bool: """ return apihelper.unhide_general_forum_topic(self.token, chat_id) + def get_forum_topic_icon_stickers(self) -> List[types.Sticker]: """ Use this method to get custom emoji stickers, which can be used as a forum topic icon by any user. @@ -5888,6 +6001,7 @@ def get_forum_topic_icon_stickers(self) -> List[types.Sticker]: """ return apihelper.get_forum_topic_icon_stickers(self.token) + def answer_web_app_query(self, web_app_query_id: str, result: types.InlineQueryResultBase) -> types.SentWebAppMessage: """ Use this method to set the result of an interaction with a Web App and @@ -5908,6 +6022,7 @@ def answer_web_app_query(self, web_app_query_id: str, result: types.InlineQueryR """ return apihelper.answer_web_app_query(self.token, web_app_query_id, result) + def register_for_reply(self, message: types.Message, callback: Callable, *args, **kwargs) -> None: """ Registers a callback function to be notified when a reply to `message` arrives. @@ -5926,8 +6041,8 @@ def register_for_reply(self, message: types.Message, callback: Callable, *args, :return: None """ - message_id = message.message_id - self.register_for_reply_by_message_id(message_id, callback, *args, **kwargs) + self.register_for_reply_by_message_id(message.message_id, callback, *args, **kwargs) + def register_for_reply_by_message_id( self, message_id: int, callback: Callable, *args, **kwargs) -> None: @@ -5950,6 +6065,7 @@ def register_for_reply_by_message_id( """ self.reply_backend.register_handler(message_id, Handler(callback, *args, **kwargs)) + def _notify_reply_handlers(self, new_messages) -> None: """ Notify handlers of the answers @@ -5964,6 +6080,7 @@ def _notify_reply_handlers(self, new_messages) -> None: for handler in handlers: self._exec_task(handler["callback"], message, *handler["args"], **handler["kwargs"]) + def register_next_step_handler(self, message: types.Message, callback: Callable, *args, **kwargs) -> None: """ Registers a callback function to be notified when new message arrives after `message`. @@ -5982,8 +6099,8 @@ def register_next_step_handler(self, message: types.Message, callback: Callable, :return: None """ - chat_id = message.chat.id - self.register_next_step_handler_by_chat_id(chat_id, callback, *args, **kwargs) + self.register_next_step_handler_by_chat_id(message.chat.id, callback, *args, **kwargs) + def setup_middleware(self, middleware: BaseMiddleware): """ @@ -6007,6 +6124,7 @@ def setup_middleware(self, middleware: BaseMiddleware): self.middlewares.append(middleware) + def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None) -> None: """ Sets a new state of a user. @@ -6032,6 +6150,7 @@ def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Option chat_id = user_id self.current_states.set_state(chat_id, user_id, state) + def reset_data(self, user_id: int, chat_id: Optional[int]=None): """ Reset data for a user in chat. @@ -6048,6 +6167,7 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None): chat_id = user_id self.current_states.reset_data(chat_id, user_id) + def delete_state(self, user_id: int, chat_id: Optional[int]=None) -> None: """ Delete the current state of a user. @@ -6064,6 +6184,7 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None) -> None: chat_id = user_id self.current_states.delete_state(chat_id, user_id) + def retrieve_data(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Any]: """ Returns context manager with data for a user in chat. @@ -6081,6 +6202,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None) -> Optional[A chat_id = user_id return self.current_states.get_interactive_data(chat_id, user_id) + def get_state(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Union[int, str, State]]: """ Gets current state of a user. @@ -6099,6 +6221,7 @@ def get_state(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Union chat_id = user_id return self.current_states.get_state(chat_id, user_id) + def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs): """ Add data to states. @@ -6117,6 +6240,7 @@ def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs): for key, value in kwargs.items(): self.current_states.set_data(chat_id, user_id, key, value) + def register_next_step_handler_by_chat_id( self, chat_id: int, callback: Callable, *args, **kwargs) -> None: """ @@ -6138,6 +6262,7 @@ def register_next_step_handler_by_chat_id( """ self.next_step_backend.register_handler(chat_id, Handler(callback, *args, **kwargs)) + def clear_step_handler(self, message: types.Message) -> None: """ Clears all callback functions registered by register_next_step_handler(). @@ -6147,8 +6272,8 @@ def clear_step_handler(self, message: types.Message) -> None: :return: None """ - chat_id = message.chat.id - self.clear_step_handler_by_chat_id(chat_id) + self.clear_step_handler_by_chat_id(message.chat.id) + def clear_step_handler_by_chat_id(self, chat_id: Union[int, str]) -> None: """ @@ -6161,6 +6286,7 @@ def clear_step_handler_by_chat_id(self, chat_id: Union[int, str]) -> None: """ self.next_step_backend.clear_handlers(chat_id) + def clear_reply_handlers(self, message: types.Message) -> None: """ Clears all callback functions registered by register_for_reply() and register_for_reply_by_message_id(). @@ -6170,8 +6296,8 @@ def clear_reply_handlers(self, message: types.Message) -> None: :return: None """ - message_id = message.message_id - self.clear_reply_handlers_by_message_id(message_id) + self.clear_reply_handlers_by_message_id(message.message_id) + def clear_reply_handlers_by_message_id(self, message_id: int) -> None: """ @@ -6184,6 +6310,7 @@ def clear_reply_handlers_by_message_id(self, message_id: int) -> None: """ self.reply_backend.clear_handlers(message_id) + def _notify_next_handlers(self, new_messages): """ Description: TBD @@ -6202,6 +6329,7 @@ def _notify_next_handlers(self, new_messages): # removing message that was detected with next_step_handler new_messages.pop(i) + @staticmethod def _build_handler_dict(handler, pass_bot=False, **filters): """ @@ -6219,6 +6347,7 @@ def _build_handler_dict(handler, pass_bot=False, **filters): #'filters': filters } + def middleware_handler(self, update_types: Optional[List[str]]=None): """ Function-based middleware handler decorator. @@ -6255,6 +6384,7 @@ def decorator(handler): return decorator + def add_middleware_handler(self, handler, update_types=None): """ Add middleware handler. @@ -6281,6 +6411,7 @@ def add_middleware_handler(self, handler, update_types=None): if not added: self.default_middleware_handlers.append(handler) + # function register_middleware_handler def register_middleware_handler(self, callback, update_types=None): """ @@ -6305,6 +6436,7 @@ def register_middleware_handler(self, callback, update_types=None): """ self.add_middleware_handler(callback, update_types) + @staticmethod def check_commands_input(commands, method_name): """ @@ -6313,6 +6445,7 @@ def check_commands_input(commands, method_name): if not isinstance(commands, list) or not all(isinstance(item, str) for item in commands): logger.error(f"{method_name}: Commands filter should be list of strings (commands), unknown type supplied to the 'commands' filter list. Not able to use the supplied type.") + @staticmethod def check_regexp_input(regexp, method_name): """ @@ -6321,6 +6454,7 @@ def check_regexp_input(regexp, method_name): if not isinstance(regexp, str): logger.error(f"{method_name}: Regexp filter should be string. Not able to use the supplied type.") + def message_handler( self, commands: Optional[List[str]]=None, @@ -6413,6 +6547,7 @@ def decorator(handler): return decorator + def add_message_handler(self, handler_dict): """ Adds a message handler @@ -6425,6 +6560,7 @@ def add_message_handler(self, handler_dict): """ self.message_handlers.append(handler_dict) + def register_message_handler(self, callback: Callable, content_types: Optional[List[str]]=None, commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, chat_types: Optional[List[str]]=None, pass_bot: Optional[bool]=False, **kwargs): """ @@ -6481,6 +6617,7 @@ def register_message_handler(self, callback: Callable, content_types: Optional[L **kwargs) self.add_message_handler(handler_dict) + def edited_message_handler(self, commands=None, regexp=None, func=None, content_types=None, chat_types=None, **kwargs): """ Handles new version of a message that is known to the bot and was edited. @@ -6535,6 +6672,7 @@ def decorator(handler): return decorator + def add_edited_message_handler(self, handler_dict): """ Adds the edit message handler @@ -6547,6 +6685,7 @@ def add_edited_message_handler(self, handler_dict): """ self.edited_message_handlers.append(handler_dict) + def register_edited_message_handler(self, callback: Callable, content_types: Optional[List[str]]=None, commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, chat_types: Optional[List[str]]=None, pass_bot: Optional[bool]=False, **kwargs): @@ -6602,6 +6741,7 @@ def register_edited_message_handler(self, callback: Callable, content_types: Opt **kwargs) self.add_edited_message_handler(handler_dict) + def channel_post_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs): """ Handles new incoming channel post of any kind - text, photo, sticker, etc. @@ -6652,6 +6792,7 @@ def decorator(handler): return decorator + def add_channel_post_handler(self, handler_dict): """ Adds channel post handler @@ -6663,8 +6804,10 @@ def add_channel_post_handler(self, handler_dict): :return: """ self.channel_post_handlers.append(handler_dict) - - def register_channel_post_handler(self, callback: Callable, content_types: Optional[List[str]]=None, commands: Optional[List[str]]=None, + + + def register_channel_post_handler( + self, callback: Callable, content_types: Optional[List[str]]=None, commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers channel post message handler. @@ -6714,6 +6857,7 @@ def register_channel_post_handler(self, callback: Callable, content_types: Optio **kwargs) self.add_channel_post_handler(handler_dict) + def edited_channel_post_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs): """ Handles new version of a channel post that is known to the bot and was edited. @@ -6764,6 +6908,7 @@ def decorator(handler): return decorator + def add_edited_channel_post_handler(self, handler_dict): """ Adds the edit channel post handler @@ -6776,8 +6921,10 @@ def add_edited_channel_post_handler(self, handler_dict): """ self.edited_channel_post_handlers.append(handler_dict) - def register_edited_channel_post_handler(self, callback: Callable, content_types: Optional[List[str]]=None, - commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): + + def register_edited_channel_post_handler( + self, callback: Callable, content_types: Optional[List[str]]=None, commands: Optional[List[str]]=None, + regexp: Optional[str]=None, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers edited channel post message handler. @@ -6845,7 +6992,8 @@ def decorator(handler): return handler return decorator - + + def add_message_reaction_handler(self, handler_dict): """ Adds message reaction handler @@ -6858,6 +7006,7 @@ def add_message_reaction_handler(self, handler_dict): """ self.message_reaction_handlers.append(handler_dict) + def register_message_reaction_handler(self, callback: Callable, func: Callable=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers message reaction handler. @@ -6878,6 +7027,7 @@ def register_message_reaction_handler(self, callback: Callable, func: Callable=N handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_message_reaction_handler(handler_dict) + def message_reaction_count_handler(self, func=None, **kwargs): """ Handles new incoming message reaction count. @@ -6896,6 +7046,7 @@ def decorator(handler): return handler return decorator + def add_message_reaction_count_handler(self, handler_dict): """ @@ -6909,6 +7060,7 @@ def add_message_reaction_count_handler(self, handler_dict): """ self.message_reaction_count_handlers.append(handler_dict) + def register_message_reaction_count_handler(self, callback: Callable, func: Callable=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers message reaction count handler. @@ -6929,6 +7081,7 @@ def register_message_reaction_count_handler(self, callback: Callable, func: Call handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_message_reaction_count_handler(handler_dict) + def inline_handler(self, func, **kwargs): """ Handles new incoming inline query. @@ -6948,6 +7101,7 @@ def decorator(handler): return decorator + def add_inline_handler(self, handler_dict): """ Adds inline call handler @@ -6960,6 +7114,7 @@ def add_inline_handler(self, handler_dict): """ self.inline_handlers.append(handler_dict) + def register_inline_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers inline handler. @@ -6980,6 +7135,7 @@ def register_inline_handler(self, callback: Callable, func: Callable, pass_bot: handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_inline_handler(handler_dict) + def chosen_inline_handler(self, func, **kwargs): """ Handles the result of an inline query that was chosen by a user and sent to their chat partner. @@ -7000,6 +7156,7 @@ def decorator(handler): return decorator + def add_chosen_inline_handler(self, handler_dict): """ Description: TBD @@ -7012,6 +7169,7 @@ def add_chosen_inline_handler(self, handler_dict): """ self.chosen_inline_handlers.append(handler_dict) + def register_chosen_inline_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers chosen inline handler. @@ -7032,6 +7190,7 @@ def register_chosen_inline_handler(self, callback: Callable, func: Callable, pas handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chosen_inline_handler(handler_dict) + def callback_query_handler(self, func, **kwargs): """ Handles new incoming callback query. @@ -7051,6 +7210,7 @@ def decorator(handler): return decorator + def add_callback_query_handler(self, handler_dict): """ Adds a callback request handler @@ -7063,6 +7223,7 @@ def add_callback_query_handler(self, handler_dict): """ self.callback_query_handlers.append(handler_dict) + def register_callback_query_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers callback query handler. @@ -7083,6 +7244,7 @@ def register_callback_query_handler(self, callback: Callable, func: Callable, pa handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_callback_query_handler(handler_dict) + def shipping_query_handler(self, func, **kwargs): """ Handles new incoming shipping query. Only for invoices with flexible price. @@ -7102,6 +7264,7 @@ def decorator(handler): return decorator + def add_shipping_query_handler(self, handler_dict): """ Adds a shipping request handler. @@ -7114,6 +7277,7 @@ def add_shipping_query_handler(self, handler_dict): """ self.shipping_query_handlers.append(handler_dict) + def register_shipping_query_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers shipping query handler. @@ -7134,6 +7298,7 @@ def register_shipping_query_handler(self, callback: Callable, func: Callable, pa handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_shipping_query_handler(handler_dict) + def pre_checkout_query_handler(self, func, **kwargs): """ New incoming pre-checkout query. Contains full information about checkout. @@ -7153,6 +7318,7 @@ def decorator(handler): return decorator + def add_pre_checkout_query_handler(self, handler_dict): """ Adds a pre-checkout request handler @@ -7164,6 +7330,7 @@ def add_pre_checkout_query_handler(self, handler_dict): :return: """ self.pre_checkout_query_handlers.append(handler_dict) + def register_pre_checkout_query_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ @@ -7184,6 +7351,7 @@ def register_pre_checkout_query_handler(self, callback: Callable, func: Callable handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_pre_checkout_query_handler(handler_dict) + def poll_handler(self, func, **kwargs): """ Handles new state of a poll. Bots receive only updates about stopped polls and polls, which are sent by the bot @@ -7202,6 +7370,7 @@ def decorator(handler): return decorator + def add_poll_handler(self, handler_dict): """ Adds a poll request handler @@ -7214,6 +7383,7 @@ def add_poll_handler(self, handler_dict): """ self.poll_handlers.append(handler_dict) + def register_poll_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers poll handler. @@ -7234,6 +7404,7 @@ def register_poll_handler(self, callback: Callable, func: Callable, pass_bot: Op handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_poll_handler(handler_dict) + def poll_answer_handler(self, func=None, **kwargs): """ Handles change of user's answer in a non-anonymous poll(when user changes the vote). @@ -7254,6 +7425,7 @@ def decorator(handler): return decorator + def add_poll_answer_handler(self, handler_dict): """ Adds a poll_answer request handler. @@ -7266,6 +7438,7 @@ def add_poll_answer_handler(self, handler_dict): """ self.poll_answer_handlers.append(handler_dict) + def register_poll_answer_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers poll answer handler. @@ -7286,6 +7459,7 @@ def register_poll_answer_handler(self, callback: Callable, func: Callable, pass_ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_poll_answer_handler(handler_dict) + def my_chat_member_handler(self, func=None, **kwargs): """ Handles update in a status of a bot. For private chats, @@ -7306,6 +7480,7 @@ def decorator(handler): return decorator + def add_my_chat_member_handler(self, handler_dict): """ Adds a my_chat_member handler. @@ -7318,6 +7493,7 @@ def add_my_chat_member_handler(self, handler_dict): """ self.my_chat_member_handlers.append(handler_dict) + def register_my_chat_member_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers my chat member handler. @@ -7338,6 +7514,7 @@ def register_my_chat_member_handler(self, callback: Callable, func: Optional[Cal handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_my_chat_member_handler(handler_dict) + def chat_member_handler(self, func=None, **kwargs): """ Handles update in a status of a user in a chat. @@ -7359,6 +7536,7 @@ def decorator(handler): return decorator + def add_chat_member_handler(self, handler_dict): """ Adds a chat_member handler. @@ -7371,7 +7549,9 @@ def add_chat_member_handler(self, handler_dict): """ self.chat_member_handlers.append(handler_dict) - def register_chat_member_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): + + def register_chat_member_handler( + self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers chat member handler. @@ -7391,6 +7571,7 @@ def register_chat_member_handler(self, callback: Callable, func: Optional[Callab handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chat_member_handler(handler_dict) + def chat_join_request_handler(self, func=None, **kwargs): """ Handles a request to join the chat has been sent. The bot must have the can_invite_users @@ -7411,6 +7592,7 @@ def decorator(handler): return decorator + def add_chat_join_request_handler(self, handler_dict): """ Adds a chat_join_request handler. @@ -7423,7 +7605,9 @@ def add_chat_join_request_handler(self, handler_dict): """ self.chat_join_request_handlers.append(handler_dict) - def register_chat_join_request_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + + def register_chat_join_request_handler( + self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): """ Registers chat join request handler. @@ -7443,6 +7627,7 @@ def register_chat_join_request_handler(self, callback: Callable, func: Optional[ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chat_join_request_handler(handler_dict) + def chat_boost_handler(self, func=None, **kwargs): """ Handles new incoming chat boost state. @@ -7460,7 +7645,8 @@ def decorator(handler): return handler return decorator - + + def add_chat_boost_handler(self, handler_dict): """ Adds a chat_boost handler. @@ -7473,7 +7659,9 @@ def add_chat_boost_handler(self, handler_dict): """ self.chat_boost_handlers.append(handler_dict) - def register_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + + def register_chat_boost_handler( + self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): """ Registers chat boost handler. @@ -7492,6 +7680,7 @@ def register_chat_boost_handler(self, callback: Callable, func: Optional[Callabl handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chat_boost_handler(handler_dict) + def removed_chat_boost_handler(self, func=None, **kwargs): """ Handles new incoming chat boost state. @@ -7509,6 +7698,7 @@ def decorator(handler): return handler return decorator + def add_removed_chat_boost_handler(self, handler_dict): """ @@ -7522,7 +7712,9 @@ def add_removed_chat_boost_handler(self, handler_dict): """ self.removed_chat_boost_handlers.append(handler_dict) - def register_removed_chat_boost_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + + def register_removed_chat_boost_handler( + self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): """ Registers removed chat boost handler. @@ -7540,24 +7732,7 @@ def register_removed_chat_boost_handler(self, callback: Callable, func: Optional """ handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_removed_chat_boost_handler(handler_dict) - - def _test_message_handler(self, message_handler, message): - """ - Test message handler - - :param message_handler: - :param message: - :return: - """ - for message_filter, filter_value in message_handler['filters'].items(): - if filter_value is None: - continue - - if not self._test_filter(message_filter, filter_value, message): - return False - - return True def add_custom_filter(self, custom_filter: Union[SimpleCustomFilter, AdvancedCustomFilter]): """ @@ -7577,6 +7752,25 @@ def check(self, message, text): """ self.custom_filters[custom_filter.key] = custom_filter + + def _test_message_handler(self, message_handler, message): + """ + Test message handler + + :param message_handler: + :param message: + :return: + """ + for message_filter, filter_value in message_handler['filters'].items(): + if filter_value is None: + continue + + if not self._test_filter(message_filter, filter_value, message): + return False + + return True + + def _test_filter(self, message_filter, filter_value, message): """ Test filters @@ -7601,6 +7795,7 @@ def _test_filter(self, message_filter, filter_value, message): else: return False + def _check_filter(self, message_filter, filter_value, message): filter_check = self.custom_filters.get(message_filter) if not filter_check: @@ -7613,6 +7808,7 @@ def _check_filter(self, message_filter, filter_value, message): logger.error("Custom filter: wrong type. Should be SimpleCustomFilter or AdvancedCustomFilter.") return False + # middleware check-up method def _get_middlewares(self, update_type): """ @@ -7626,6 +7822,7 @@ def _get_middlewares(self, update_type): middlewares = [i for i in self.middlewares if update_type in i.update_types] return middlewares + def _run_middlewares_and_handler(self, message, handlers, middlewares, update_type): """ This method is made to run handlers and middlewares in queue. @@ -7636,7 +7833,6 @@ def _run_middlewares_and_handler(self, message, handlers, middlewares, update_ty :param update_type: handler/update type (Update field name) :return: """ - if not self.use_class_middlewares: if handlers: for handler in handlers: @@ -7719,6 +7915,7 @@ def _run_middlewares_and_handler(self, message, handlers, middlewares, update_ty else: middleware.post_process(message, data, handler_error) + def _notify_command_handlers(self, handlers, new_messages, update_type): """ Notifies command handlers. From 60d581f9ea79cc9362d01f59f39debbd1f58bcd1 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Jan 2024 23:48:59 +0300 Subject: [PATCH 104/480] Fix UserShared with UsersShared --- telebot/types.py | 54 +++++++++++++----------------------------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 58843f7e3..7c945f40b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -992,7 +992,7 @@ class Message(JsonDeserializable): :type successful_payment: :class:`telebot.types.SuccessfulPayment` :param users_shared: Optional. Service message: a user was shared with the bot - :type users_shared: :class:`telebot.types.UserShared` + :type users_shared: :class:`telebot.types.UsersShared` :param chat_shared: Optional. Service message: a chat was shared with the bot :type chat_shared: :class:`telebot.types.ChatShared` @@ -1242,7 +1242,7 @@ def de_json(cls, json_string): opts['write_access_allowed'] = WriteAccessAllowed.de_json(obj['write_access_allowed']) content_type = 'write_access_allowed' if 'users_shared' in obj: - opts['users_shared'] = UserShared.de_json(obj['users_shared']) + opts['users_shared'] = UsersShared.de_json(obj['users_shared']) content_type = 'users_shared' # COMPATIBILITY BROKEN! if 'chat_shared' in obj: opts['chat_shared'] = ChatShared.de_json(obj['chat_shared']) @@ -1359,8 +1359,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.general_forum_topic_hidden: Optional[GeneralForumTopicHidden] = None self.general_forum_topic_unhidden: Optional[GeneralForumTopicUnhidden] = None self.write_access_allowed: Optional[WriteAccessAllowed] = None - self.users_shared: Optional[UserShared] = None - self.user_shared: Optional[UserShared] = self.users_shared + self.users_shared: Optional[UsersShared] = None self.chat_shared: Optional[ChatShared] = None self.story: Optional[Story] = None self.external_reply: Optional[ExternalReplyInfo] = None @@ -1561,6 +1560,10 @@ def forward_date(self): return self.forward_origin.date return None + @property + def user_shared(self): + logger.warning('The parameter "user_shared" is deprecated, use "users_shared" instead') + return self.users_shared class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): @@ -2464,7 +2467,7 @@ class KeyboardButtonRequestUsers(Dictionaryable): Telegram documentation: https://core.telegram.org/bots/api#keyboardbuttonrequestusers - :param request_id: Signed 32-bit identifier of the request, which will be received back in the UserShared object. + :param request_id: Signed 32-bit identifier of the request, which will be received back in the UsersShared object. Must be unique within the message :type request_id: :obj:`int` @@ -2601,7 +2604,7 @@ class KeyboardButton(Dictionaryable, JsonSerializable): :type web_app: :class:`telebot.types.WebAppInfo` :param request_user: Optional. If specified, pressing the button will open a list of suitable users. Tapping on any user - will send their identifier to the bot in a “user_shared” service message. Available in private chats only. + will send their identifier to the bot in a “users_shared” service message. Available in private chats only. :type request_user: :class:`telebot.types.KeyboardButtonRequestUsers` :param request_chat: Optional. If specified, pressing the button will open a list of suitable chats. Tapping on a chat will @@ -7732,41 +7735,8 @@ def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str self.web_app_name: str = web_app_name self.from_request: bool = from_request self.from_attachment_menu: bool = from_attachment_menu - - - -class UserShared(JsonDeserializable): - """ - This object contains information about the user whose identifier was shared with the bot using a - `telebot.types.KeyboardButtonRequestUsers` button. - - Telegram documentation: https://core.telegram.org/bots/api#usershared - :param request_id: identifier of the request - :type request_id: :obj:`int` - :param user_id: Identifier of the shared user. This number may have more than 32 significant bits and some programming - languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a 64-bit - integer or double-precision float type are safe for storing this identifier. The bot may not have access to the user - and could be unable to use this identifier, unless the user is already known to the bot by some other means. - :type user_id: :obj:`int` - - :return: Instance of the class - :rtype: :class:`telebot.types.UserShared` - """ - - @classmethod - def de_json(cls, json_string): - if json_string is None: return None - obj = cls.check_json(json_string) - return cls(**obj) - - def __init__(self, request_id: int, user_id: int, **kwargs) -> None: - self.request_id: int = request_id - self.user_id: int = user_id - - - class ChatShared(JsonDeserializable): """ This object contains information about the chat whose identifier was shared with the bot using a @@ -8918,7 +8888,6 @@ class UsersShared(JsonDeserializable): :return: Instance of the class :rtype: :class:`UsersShared` """ - @classmethod def de_json(cls, json_string): if json_string is None: @@ -8929,6 +8898,11 @@ def de_json(cls, json_string): def __init__(self, request_id, user_ids, **kwargs): self.request_id = request_id self.user_ids = user_ids + + @property + def user_id(self): + logger.warning('The parameter "user_id" is deprecated, use "user_ids" instead') + return None class ChatBoostUpdated(JsonDeserializable): From 071fff34ff636e450d9aa44a7a8f740602407c7f Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 4 Jan 2024 00:10:04 +0300 Subject: [PATCH 105/480] Deprecation fixes N2 request_user deprecated, request_users updates. Classes also. --- telebot/types.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 7c945f40b..da41be80a 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2484,10 +2484,10 @@ class KeyboardButtonRequestUsers(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.KeyboardButtonRequestUsers` - """ - - def __init__(self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, max_quantity: Optional[int]=None) -> None: + def __init__( + self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, + max_quantity: Optional[int]=None) -> None: self.request_id: int = request_id self.user_is_bot: Optional[bool] = user_is_bot self.user_is_premium: Optional[bool] = user_is_premium @@ -2503,7 +2503,15 @@ def to_dict(self) -> dict: data['max_quantity'] = self.max_quantity return data -KeyboardButtonRequestUser = KeyboardButtonRequestUsers + +class KeyboardButtonRequestUser(KeyboardButtonRequestUsers): + """Deprecated. Use KeyboardButtonRequestUsers instead.""" + def __init__( + self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, + max_quantity: Optional[int]=None) -> None: + logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') + super().__init__(request_id, user_is_bot=user_is_bot, user_is_premium=user_is_premium, max_quantity=max_quantity) + class KeyboardButtonRequestChat(Dictionaryable): """ @@ -2603,9 +2611,12 @@ class KeyboardButton(Dictionaryable, JsonSerializable): will be able to send a “web_app_data” service message. Available in private chats only. :type web_app: :class:`telebot.types.WebAppInfo` - :param request_user: Optional. If specified, pressing the button will open a list of suitable users. Tapping on any user - will send their identifier to the bot in a “users_shared” service message. Available in private chats only. - :type request_user: :class:`telebot.types.KeyboardButtonRequestUsers` + :param request_user: deprecated + :type request_user: :class:`telebot.types.KeyboardButtonRequestUser` + + :param request_users: Optional. If specified, pressing the button will open a list of suitable users. + Identifiers of selected users will be sent to the bot in a “users_shared” service message. Available in private chats only. + :type request_users: :class:`telebot.types.KeyboardButtonRequestUsers` :param request_chat: Optional. If specified, pressing the button will open a list of suitable chats. Tapping on a chat will send its identifier to the bot in a “chat_shared” service message. Available in private chats only. @@ -2616,18 +2627,19 @@ class KeyboardButton(Dictionaryable, JsonSerializable): """ def __init__(self, text: str, request_contact: Optional[bool]=None, request_location: Optional[bool]=None, request_poll: Optional[KeyboardButtonPollType]=None, - web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUsers]=None, + web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUser]=None, request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None): self.text: str = text self.request_contact: bool = request_contact self.request_location: bool = request_location self.request_poll: KeyboardButtonPollType = request_poll self.web_app: WebAppInfo = web_app - self.request_user: KeyboardButtonRequestUsers = request_user self.request_chat: KeyboardButtonRequestChat = request_chat self.request_users: KeyboardButtonRequestUsers = request_users if request_user is not None: - self.request_users = request_user + logger.warning('The parameter "request_user" is deprecated, use "request_users" instead') + if self.request_users is None: + self.request_users = request_user def to_json(self): @@ -2643,8 +2655,8 @@ def to_dict(self): json_dict['request_poll'] = self.request_poll.to_dict() if self.web_app is not None: json_dict['web_app'] = self.web_app.to_dict() - if self.request_user is not None: - json_dict['request_user'] = self.request_user.to_dict() + if self.request_users is not None: + json_dict['request_users'] = self.request_users.to_dict() if self.request_chat is not None: json_dict['request_chat'] = self.request_chat.to_dict() return json_dict From 71cdf48b5bc2591d6356705e24047b483de015c8 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 4 Jan 2024 00:53:55 +0300 Subject: [PATCH 106/480] New content_types added --- telebot/__init__.py | 2 +- telebot/types.py | 4 +++- telebot/util.py | 20 +++++++++++--------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 13fdda5a2..fb49abdc0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4410,7 +4410,7 @@ def edit_message_text( :param entities: List of special entities that appear in the message text, which can be specified instead of parse_mode :type entities: List of :obj:`telebot.types.MessageEntity` - :param disable_web_page_preview: deprecated. Disables link previews for links in this message + :param disable_web_page_preview: deprecated. :type disable_web_page_preview: :obj:`bool` :param reply_markup: A JSON-serialized object for an inline keyboard. diff --git a/telebot/types.py b/telebot/types.py index da41be80a..72d631f8c 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3797,7 +3797,9 @@ class InputTextMessageContent(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.InputTextMessageContent` """ - def __init__(self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None, link_preview_options=None): + def __init__( + self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None, + link_preview_options=None): self.message_text: str = message_text self.parse_mode: str = parse_mode self.entities: List[MessageEntity] = entities diff --git a/telebot/util.py b/telebot/util.py index 9f0c7ab4c..94622fcb7 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -27,18 +27,20 @@ #: Contains all media content types. content_type_media = [ - 'text', 'audio', 'document', 'animation', 'game', 'photo', 'sticker', 'video', 'video_note', 'voice', 'contact', - 'location', 'venue', 'dice', 'invoice', 'successful_payment', 'connected_website', 'poll', 'passport_data', - 'web_app_data', + 'text', 'animation', 'audio', 'document', 'photo', 'sticker', 'story', 'video', 'video_note', 'voice', 'contact', + 'dice', 'game', 'poll', 'venue', 'location', 'invoice', 'successful_payment', 'connected_website', + 'passport_data', 'web_app_data', ] #: Contains all service content types such as `User joined the group`. content_type_service = [ 'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', - 'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id', - 'migrate_from_chat_id', 'pinned_message', 'proximity_alert_triggered', 'video_chat_scheduled', 'video_chat_started', - 'video_chat_ended', 'video_chat_participants_invited', 'message_auto_delete_timer_changed', 'forum_topic_created', - 'forum_topic_closed', 'forum_topic_reopened', 'user_shared', 'chat_shared', + 'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'message_auto_delete_timer_changed', + 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message', 'users_shared', 'chat_shared', + 'write_access_allowed', 'proximity_alert_triggered', 'forum_topic_created', 'forum_topic_edited', + 'forum_topic_closed', 'forum_topic_reopened', 'general_forum_topic_hidden', 'general_forum_topic_unhidden', + 'giveaway_created', 'giveaway', 'giveaway_winners', 'giveaway_completed', 'video_chat_scheduled', + 'video_chat_started', 'video_chat_ended', 'video_chat_participants_invited', ] #: All update types, should be used for allowed_updates parameter in polling. @@ -187,7 +189,7 @@ def wait(self): return self.result -class CustomRequestResponse(): +class CustomRequestResponse: """ :meta private: """ @@ -365,7 +367,7 @@ def _text_before_last(substr: str) -> str: text = text[len(part):] -def escape(text: str) -> str: +def escape(text: str) -> Optional[str]: """ Replaces the following chars in `text` ('&' with '&', '<' with '<' and '>' with '>'). From 45434299afe90d6c56cb7de231f665d01e0f9227 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 4 Jan 2024 01:33:25 +0300 Subject: [PATCH 107/480] MaybeInaccessibleMessage processing Improved documentation for the field message of the class callbackQuery and the field pinned_message of the class Message by adding the classes MaybeInaccessibleMessage and InaccessibleMessage. --- telebot/types.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 72d631f8c..e0a578220 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -982,7 +982,7 @@ class Message(JsonDeserializable): :param pinned_message: Optional. Specified message was pinned. Note that the Message object in this field will not contain further reply_to_message fields even if it is itself a reply. - :type pinned_message: :class:`telebot.types.Message` + :type message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » :type invoice: :class:`telebot.types.Invoice` @@ -1177,7 +1177,12 @@ def de_json(cls, json_string): opts['migrate_from_chat_id'] = obj['migrate_from_chat_id'] content_type = 'migrate_from_chat_id' if 'pinned_message' in obj: - opts['pinned_message'] = Message.de_json(obj['pinned_message']) + pinned_message = obj['pinned_message'] + if pinned_message['date'] == 0: + # date. Always 0. The field can be used to differentiate regular and inaccessible messages. + opts['pinned_message'] = InaccessibleMessage.de_json(pinned_message) + else: + opts['pinned_message'] = Message.de_json(pinned_message) content_type = 'pinned_message' if 'invoice' in obj: opts['invoice'] = Invoice.de_json(obj['invoice']) @@ -1344,7 +1349,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.channel_chat_created: Optional[bool] = None self.migrate_to_chat_id: Optional[int] = None self.migrate_from_chat_id: Optional[int] = None - self.pinned_message: Optional[Message] = None + self.pinned_message: Union[Message, InaccessibleMessage] = message self.invoice: Optional[Invoice] = None self.successful_payment: Optional[SuccessfulPayment] = None self.connected_website: Optional[str] = None @@ -2944,9 +2949,8 @@ class CallbackQuery(JsonDeserializable): :param from_user: Sender :type from_user: :class:`telebot.types.User` - :param message: Optional. Message with the callback button that originated the query. Note that message content and - message date will not be available if the message is too old - :type message: :class:`telebot.types.Message` + :param message: Optional. Message sent by the bot with the callback button that originated the query + :type message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` :param inline_message_id: Optional. Identifier of the message sent via the bot in inline mode, that originated the query. @@ -2975,14 +2979,21 @@ def de_json(cls, json_string): obj['data'] = None obj['from_user'] = User.de_json(obj.pop('from')) if 'message' in obj: - obj['message'] = Message.de_json(obj.get('message')) + message = obj['message'] + if message['date'] == 0: + # date. Always 0. The field can be used to differentiate regular and inaccessible messages. + obj['message'] = InaccessibleMessage.de_json(message) + else: + obj['message'] = Message.de_json(message) obj['json_string'] = json_string return cls(**obj) - def __init__(self, id, from_user, data, chat_instance, json_string, message=None, inline_message_id=None, game_short_name=None, **kwargs): + def __init__( + self, id, from_user, data, chat_instance, json_string, message=None, inline_message_id=None, + game_short_name=None, **kwargs): self.id: int = id self.from_user: User = from_user - self.message: Message = message + self.message: Union[Message, InaccessibleMessage] = message self.inline_message_id: str = inline_message_id self.chat_instance: str = chat_instance self.data: str = data From 8bc3d1cc1657aefa45ae5fba8c998873f32ff8ef Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 4 Jan 2024 01:37:51 +0300 Subject: [PATCH 108/480] MaybeInaccessibleMessage processing fix --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index e0a578220..82efd0216 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1349,7 +1349,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.channel_chat_created: Optional[bool] = None self.migrate_to_chat_id: Optional[int] = None self.migrate_from_chat_id: Optional[int] = None - self.pinned_message: Union[Message, InaccessibleMessage] = message + self.pinned_message: Optional[Union[Message, InaccessibleMessage]] = None self.invoice: Optional[Invoice] = None self.successful_payment: Optional[SuccessfulPayment] = None self.connected_website: Optional[str] = None From cb0540ba2461a59cf42c1bd5e3ec404d713230af Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 5 Jan 2024 17:01:39 +0300 Subject: [PATCH 109/480] Formatting fix. --- telebot/types.py | 398 +++++++++++++++++++++++------------------------ 1 file changed, 199 insertions(+), 199 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 82efd0216..3da07f7ac 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -785,285 +785,285 @@ def to_dict(self): # noinspection PyUnresolvedReferences class Message(JsonDeserializable): """ - This object represents a message. + This object represents a message. - Telegram Documentation: https://core.telegram.org/bots/api#message + Telegram Documentation: https://core.telegram.org/bots/api#message - :param message_id: Unique message identifier inside this chat - :type message_id: :obj:`int` - - :param message_thread_id: Optional. Unique identifier of a message thread to which the message belongs; for supergroups only - :type message_thread_id: :obj:`int` - - :param from_user: Optional. Sender of the message; empty for messages sent to channels. For backward compatibility, the - field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. - :type from_user: :class:`telebot.types.User` + :param message_id: Unique message identifier inside this chat + :type message_id: :obj:`int` - :param sender_chat: Optional. Sender of the message, sent on behalf of a chat. For example, the channel itself for - channel posts, the supergroup itself for messages from anonymous group administrators, the linked channel for - messages automatically forwarded to the discussion group. For backward compatibility, the field from contains a - fake sender user in non-channel chats, if the message was sent on behalf of a chat. - :type sender_chat: :class:`telebot.types.Chat` + :param message_thread_id: Optional. Unique identifier of a message thread to which the message belongs; for supergroups only + :type message_thread_id: :obj:`int` - :param date: Date the message was sent in Unix time - :type date: :obj:`int` + :param from_user: Optional. Sender of the message; empty for messages sent to channels. For backward compatibility, the + field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. + :type from_user: :class:`telebot.types.User` - :param chat: Conversation the message belongs to - :type chat: :class:`telebot.types.Chat` + :param sender_chat: Optional. Sender of the message, sent on behalf of a chat. For example, the channel itself for + channel posts, the supergroup itself for messages from anonymous group administrators, the linked channel for + messages automatically forwarded to the discussion group. For backward compatibility, the field from contains a + fake sender user in non-channel chats, if the message was sent on behalf of a chat. + :type sender_chat: :class:`telebot.types.Chat` - :param forward_from: deprecated. - :type forward_from: :class:`telebot.types.User` + :param date: Date the message was sent in Unix time + :type date: :obj:`int` - :param forward_from_chat: deprecated. - :type forward_from_chat: :class:`telebot.types.Chat` + :param chat: Conversation the message belongs to + :type chat: :class:`telebot.types.Chat` - :param forward_from_message_id: deprecated. - message in the channel - :type forward_from_message_id: :obj:`int` + :param forward_from: deprecated. + :type forward_from: :class:`telebot.types.User` - :param forward_signature: deprecated. - :type forward_signature: :obj:`str` + :param forward_from_chat: deprecated. + :type forward_from_chat: :class:`telebot.types.Chat` - :param forward_sender_name: deprecated. - :type forward_sender_name: :obj:`str` + :param forward_from_message_id: deprecated. + message in the channel + :type forward_from_message_id: :obj:`int` - :param forward_date: deprecated. - :type forward_date: :obj:`int` + :param forward_signature: deprecated. + :type forward_signature: :obj:`str` - :forward_origin: Optional. For forwarded messages, information about the original message; - :type forward_origin: :class:`telebot.types.MessageOrigin` + :param forward_sender_name: deprecated. + :type forward_sender_name: :obj:`str` - :param is_topic_message: Optional. True, if the message is sent to a forum topic - :type is_topic_message: :obj:`bool` + :param forward_date: deprecated. + :type forward_date: :obj:`int` - :param is_automatic_forward: Optional. :obj:`bool`, if the message is a channel post that was automatically - forwarded to the connected discussion group - :type is_automatic_forward: :obj:`bool` + :forward_origin: Optional. For forwarded messages, information about the original message; + :type forward_origin: :class:`telebot.types.MessageOrigin` - :param reply_to_message: Optional. For replies, the original message. Note that the Message object in this field - will not contain further reply_to_message fields even if it itself is a reply. - :type reply_to_message: :class:`telebot.types.Message` + :param is_topic_message: Optional. True, if the message is sent to a forum topic + :type is_topic_message: :obj:`bool` - :param external_reply: Optional. Information about the message that is being replied to, which may come from another chat or forum topic - :type external_reply: :class:`telebot.types.ExternalReplyInfo` + :param is_automatic_forward: Optional. :obj:`bool`, if the message is a channel post that was automatically + forwarded to the connected discussion group + :type is_automatic_forward: :obj:`bool` - :param quote: Optional. For replies that quote part of the original message, the quoted part of the message - :type quote: :class:`telebot.types.TextQuote` + :param reply_to_message: Optional. For replies, the original message. Note that the Message object in this field + will not contain further reply_to_message fields even if it itself is a reply. + :type reply_to_message: :class:`telebot.types.Message` - :param via_bot: Optional. Bot through which the message was sent - :type via_bot: :class:`telebot.types.User` + :param external_reply: Optional. Information about the message that is being replied to, which may come from another chat or forum topic + :type external_reply: :class:`telebot.types.ExternalReplyInfo` - :param edit_date: Optional. Date the message was last edited in Unix time - :type edit_date: :obj:`int` + :param quote: Optional. For replies that quote part of the original message, the quoted part of the message + :type quote: :class:`telebot.types.TextQuote` - :param has_protected_content: Optional. :obj:`bool`, if the message can't be forwarded - :type has_protected_content: :obj:`bool` + :param via_bot: Optional. Bot through which the message was sent + :type via_bot: :class:`telebot.types.User` - :param media_group_id: Optional. The unique identifier of a media message group this message belongs to - :type media_group_id: :obj:`str` + :param edit_date: Optional. Date the message was last edited in Unix time + :type edit_date: :obj:`int` - :param author_signature: Optional. Signature of the post author for messages in channels, or the custom title of an - anonymous group administrator - :type author_signature: :obj:`str` + :param has_protected_content: Optional. :obj:`bool`, if the message can't be forwarded + :type has_protected_content: :obj:`bool` - :param text: Optional. For text messages, the actual UTF-8 text of the message - :type text: :obj:`str` + :param media_group_id: Optional. The unique identifier of a media message group this message belongs to + :type media_group_id: :obj:`str` - :param entities: Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that - appear in the text - :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :param author_signature: Optional. Signature of the post author for messages in channels, or the custom title of an + anonymous group administrator + :type author_signature: :obj:`str` - :param link_preview_options: Optional. Options used for link preview generation for the message, - if it is a text message and link preview options were changed - :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param text: Optional. For text messages, the actual UTF-8 text of the message + :type text: :obj:`str` - :param animation: Optional. Message is an animation, information about the animation. For backward - compatibility, when this field is set, the document field will also be set - :type animation: :class:`telebot.types.Animation` + :param entities: Optional. For text messages, special entities like usernames, URLs, bot commands, etc. that + appear in the text + :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param audio: Optional. Message is an audio file, information about the file - :type audio: :class:`telebot.types.Audio` + :param link_preview_options: Optional. Options used for link preview generation for the message, + if it is a text message and link preview options were changed + :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` - :param document: Optional. Message is a general file, information about the file - :type document: :class:`telebot.types.Document` + :param animation: Optional. Message is an animation, information about the animation. For backward + compatibility, when this field is set, the document field will also be set + :type animation: :class:`telebot.types.Animation` - :param photo: Optional. Message is a photo, available sizes of the photo - :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` + :param audio: Optional. Message is an audio file, information about the file + :type audio: :class:`telebot.types.Audio` - :param sticker: Optional. Message is a sticker, information about the sticker - :type sticker: :class:`telebot.types.Sticker` + :param document: Optional. Message is a general file, information about the file + :type document: :class:`telebot.types.Document` - :param story: Optional. Message is a forwarded story - :type story: :class:`telebot.types.Story` + :param photo: Optional. Message is a photo, available sizes of the photo + :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` - :param video: Optional. Message is a video, information about the video - :type video: :class:`telebot.types.Video` + :param sticker: Optional. Message is a sticker, information about the sticker + :type sticker: :class:`telebot.types.Sticker` - :param video_note: Optional. Message is a video note, information about the video message - :type video_note: :class:`telebot.types.VideoNote` + :param story: Optional. Message is a forwarded story + :type story: :class:`telebot.types.Story` - :param voice: Optional. Message is a voice message, information about the file - :type voice: :class:`telebot.types.Voice` + :param video: Optional. Message is a video, information about the video + :type video: :class:`telebot.types.Video` - :param caption: Optional. Caption for the animation, audio, document, photo, video or voice - :type caption: :obj:`str` + :param video_note: Optional. Message is a video note, information about the video message + :type video_note: :class:`telebot.types.VideoNote` - :param caption_entities: Optional. For messages with a caption, special entities like usernames, URLs, bot - commands, etc. that appear in the caption - :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :param voice: Optional. Message is a voice message, information about the file + :type voice: :class:`telebot.types.Voice` - :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation - :type has_media_spoiler: :obj:`bool` + :param caption: Optional. Caption for the animation, audio, document, photo, video or voice + :type caption: :obj:`str` - :param contact: Optional. Message is a shared contact, information about the contact - :type contact: :class:`telebot.types.Contact` + :param caption_entities: Optional. For messages with a caption, special entities like usernames, URLs, bot + commands, etc. that appear in the caption + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param dice: Optional. Message is a dice with random value - :type dice: :class:`telebot.types.Dice` + :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation + :type has_media_spoiler: :obj:`bool` - :param game: Optional. Message is a game, information about the game. More about games » - :type game: :class:`telebot.types.Game` + :param contact: Optional. Message is a shared contact, information about the contact + :type contact: :class:`telebot.types.Contact` - :param poll: Optional. Message is a native poll, information about the poll - :type poll: :class:`telebot.types.Poll` + :param dice: Optional. Message is a dice with random value + :type dice: :class:`telebot.types.Dice` - :param venue: Optional. Message is a venue, information about the venue. For backward compatibility, when this - field is set, the location field will also be set - :type venue: :class:`telebot.types.Venue` + :param game: Optional. Message is a game, information about the game. More about games » + :type game: :class:`telebot.types.Game` - :param location: Optional. Message is a shared location, information about the location - :type location: :class:`telebot.types.Location` + :param poll: Optional. Message is a native poll, information about the poll + :type poll: :class:`telebot.types.Poll` - :param new_chat_members: Optional. New members that were added to the group or supergroup and information about - them (the bot itself may be one of these members) - :type new_chat_members: :obj:`list` of :class:`telebot.types.User` + :param venue: Optional. Message is a venue, information about the venue. For backward compatibility, when this + field is set, the location field will also be set + :type venue: :class:`telebot.types.Venue` - :param left_chat_member: Optional. A member was removed from the group, information about them (this member may be - the bot itself) - :type left_chat_member: :class:`telebot.types.User` + :param location: Optional. Message is a shared location, information about the location + :type location: :class:`telebot.types.Location` - :param new_chat_title: Optional. A chat title was changed to this value - :type new_chat_title: :obj:`str` + :param new_chat_members: Optional. New members that were added to the group or supergroup and information about + them (the bot itself may be one of these members) + :type new_chat_members: :obj:`list` of :class:`telebot.types.User` - :param new_chat_photo: Optional. A chat photo was change to this value - :type new_chat_photo: :obj:`list` of :class:`telebot.types.PhotoSize` + :param left_chat_member: Optional. A member was removed from the group, information about them (this member may be + the bot itself) + :type left_chat_member: :class:`telebot.types.User` - :param delete_chat_photo: Optional. Service message: the chat photo was deleted - :type delete_chat_photo: :obj:`bool` + :param new_chat_title: Optional. A chat title was changed to this value + :type new_chat_title: :obj:`str` - :param group_chat_created: Optional. Service message: the group has been created - :type group_chat_created: :obj:`bool` + :param new_chat_photo: Optional. A chat photo was change to this value + :type new_chat_photo: :obj:`list` of :class:`telebot.types.PhotoSize` - :param supergroup_chat_created: Optional. Service message: the supergroup has been created. This field can't be - received in a message coming through updates, because bot can't be a member of a supergroup when it is created. It can - only be found in reply_to_message if someone replies to a very first message in a directly created supergroup. - :type supergroup_chat_created: :obj:`bool` + :param delete_chat_photo: Optional. Service message: the chat photo was deleted + :type delete_chat_photo: :obj:`bool` - :param channel_chat_created: Optional. Service message: the channel has been created. This field can't be - received in a message coming through updates, because bot can't be a member of a channel when it is created. It can only - be found in reply_to_message if someone replies to a very first message in a channel. - :type channel_chat_created: :obj:`bool` + :param group_chat_created: Optional. Service message: the group has been created + :type group_chat_created: :obj:`bool` - :param message_auto_delete_timer_changed: Optional. Service message: auto-delete timer settings changed in - the chat - :type message_auto_delete_timer_changed: :class:`telebot.types.MessageAutoDeleteTimerChanged` + :param supergroup_chat_created: Optional. Service message: the supergroup has been created. This field can't be + received in a message coming through updates, because bot can't be a member of a supergroup when it is created. It can + only be found in reply_to_message if someone replies to a very first message in a directly created supergroup. + :type supergroup_chat_created: :obj:`bool` - :param migrate_to_chat_id: Optional. The group has been migrated to a supergroup with the specified identifier. - This number may have more than 32 significant bits and some programming languages may have difficulty/silent - defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision - float type are safe for storing this identifier. - :type migrate_to_chat_id: :obj:`int` + :param channel_chat_created: Optional. Service message: the channel has been created. This field can't be + received in a message coming through updates, because bot can't be a member of a channel when it is created. It can only + be found in reply_to_message if someone replies to a very first message in a channel. + :type channel_chat_created: :obj:`bool` - :param migrate_from_chat_id: Optional. The supergroup has been migrated from a group with the specified - identifier. This number may have more than 32 significant bits and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or - double-precision float type are safe for storing this identifier. - :type migrate_from_chat_id: :obj:`int` + :param message_auto_delete_timer_changed: Optional. Service message: auto-delete timer settings changed in + the chat + :type message_auto_delete_timer_changed: :class:`telebot.types.MessageAutoDeleteTimerChanged` - :param pinned_message: Optional. Specified message was pinned. Note that the Message object in this field will not - contain further reply_to_message fields even if it is itself a reply. - :type message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` + :param migrate_to_chat_id: Optional. The group has been migrated to a supergroup with the specified identifier. + This number may have more than 32 significant bits and some programming languages may have difficulty/silent + defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision + float type are safe for storing this identifier. + :type migrate_to_chat_id: :obj:`int` + + :param migrate_from_chat_id: Optional. The supergroup has been migrated from a group with the specified + identifier. This number may have more than 32 significant bits and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + double-precision float type are safe for storing this identifier. + :type migrate_from_chat_id: :obj:`int` + + :param pinned_message: Optional. Specified message was pinned. Note that the Message object in this field will not + contain further reply_to_message fields even if it is itself a reply. + :type message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` - :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » - :type invoice: :class:`telebot.types.Invoice` + :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » + :type invoice: :class:`telebot.types.Invoice` - :param successful_payment: Optional. Message is a service message about a successful payment, information about - the payment. More about payments » - :type successful_payment: :class:`telebot.types.SuccessfulPayment` + :param successful_payment: Optional. Message is a service message about a successful payment, information about + the payment. More about payments » + :type successful_payment: :class:`telebot.types.SuccessfulPayment` - :param users_shared: Optional. Service message: a user was shared with the bot - :type users_shared: :class:`telebot.types.UsersShared` + :param users_shared: Optional. Service message: a user was shared with the bot + :type users_shared: :class:`telebot.types.UsersShared` - :param chat_shared: Optional. Service message: a chat was shared with the bot - :type chat_shared: :class:`telebot.types.ChatShared` + :param chat_shared: Optional. Service message: a chat was shared with the bot + :type chat_shared: :class:`telebot.types.ChatShared` - :param connected_website: Optional. The domain name of the website on which the user has logged in. More about - Telegram Login » - :type connected_website: :obj:`str` + :param connected_website: Optional. The domain name of the website on which the user has logged in. More about + Telegram Login » + :type connected_website: :obj:`str` - :param write_access_allowed: Optional. Service message: the user allowed the bot added to the attachment - menu to write messages - :type write_access_allowed: :class:`telebot.types.WriteAccessAllowed` + :param write_access_allowed: Optional. Service message: the user allowed the bot added to the attachment + menu to write messages + :type write_access_allowed: :class:`telebot.types.WriteAccessAllowed` - :param passport_data: Optional. Telegram Passport data - :type passport_data: :class:`telebot.types.PassportData` + :param passport_data: Optional. Telegram Passport data + :type passport_data: :class:`telebot.types.PassportData` - :param proximity_alert_triggered: Optional. Service message. A user in the chat triggered another user's - proximity alert while sharing Live Location. - :type proximity_alert_triggered: :class:`telebot.types.ProximityAlertTriggered` + :param proximity_alert_triggered: Optional. Service message. A user in the chat triggered another user's + proximity alert while sharing Live Location. + :type proximity_alert_triggered: :class:`telebot.types.ProximityAlertTriggered` - :param forum_topic_created: Optional. Service message: forum topic created - :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` + :param forum_topic_created: Optional. Service message: forum topic created + :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` - :param forum_topic_edited: Optional. Service message: forum topic edited - :type forum_topic_edited: :class:`telebot.types.ForumTopicEdited` + :param forum_topic_edited: Optional. Service message: forum topic edited + :type forum_topic_edited: :class:`telebot.types.ForumTopicEdited` - :param forum_topic_closed: Optional. Service message: forum topic closed - :type forum_topic_closed: :class:`telebot.types.ForumTopicClosed` + :param forum_topic_closed: Optional. Service message: forum topic closed + :type forum_topic_closed: :class:`telebot.types.ForumTopicClosed` - :param forum_topic_reopened: Optional. Service message: forum topic reopened - :type forum_topic_reopened: :class:`telebot.types.ForumTopicReopened` + :param forum_topic_reopened: Optional. Service message: forum topic reopened + :type forum_topic_reopened: :class:`telebot.types.ForumTopicReopened` - :param general_forum_topic_hidden: Optional. Service message: the 'General' forum topic hidden - :type general_forum_topic_hidden: :class:`telebot.types.GeneralForumTopicHidden` + :param general_forum_topic_hidden: Optional. Service message: the 'General' forum topic hidden + :type general_forum_topic_hidden: :class:`telebot.types.GeneralForumTopicHidden` - :param general_forum_topic_unhidden: Optional. Service message: the 'General' forum topic unhidden - :type general_forum_topic_unhidden: :class:`telebot.types.GeneralForumTopicUnhidden` + :param general_forum_topic_unhidden: Optional. Service message: the 'General' forum topic unhidden + :type general_forum_topic_unhidden: :class:`telebot.types.GeneralForumTopicUnhidden` - :param giveaway_created: Optional. Service message: a giveaway has been created - :type giveaway_created: :class:`telebot.types.GiveawayCreated` + :param giveaway_created: Optional. Service message: a giveaway has been created + :type giveaway_created: :class:`telebot.types.GiveawayCreated` - :param giveaway: Optional. The message is a scheduled giveaway message - :type giveaway: :class:`telebot.types.Giveaway` + :param giveaway: Optional. The message is a scheduled giveaway message + :type giveaway: :class:`telebot.types.Giveaway` - :param giveaway_winners: Optional. Service message: giveaway winners(public winners) - :type giveaway_winners: :class:`telebot.types.GiveawayWinners` + :param giveaway_winners: Optional. Service message: giveaway winners(public winners) + :type giveaway_winners: :class:`telebot.types.GiveawayWinners` - :param giveaway_completed: Optional. Service message: giveaway completed, without public winners - :type giveaway_completed: :class:`telebot.types.GiveawayCompleted` + :param giveaway_completed: Optional. Service message: giveaway completed, without public winners + :type giveaway_completed: :class:`telebot.types.GiveawayCompleted` - :param video_chat_scheduled: Optional. Service message: video chat scheduled - :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` + :param video_chat_scheduled: Optional. Service message: video chat scheduled + :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` - :param video_chat_started: Optional. Service message: video chat started - :type video_chat_started: :class:`telebot.types.VideoChatStarted` + :param video_chat_started: Optional. Service message: video chat started + :type video_chat_started: :class:`telebot.types.VideoChatStarted` - :param video_chat_ended: Optional. Service message: video chat ended - :type video_chat_ended: :class:`telebot.types.VideoChatEnded` + :param video_chat_ended: Optional. Service message: video chat ended + :type video_chat_ended: :class:`telebot.types.VideoChatEnded` - :param video_chat_participants_invited: Optional. Service message: new participants invited to a video chat - :type video_chat_participants_invited: :class:`telebot.types.VideoChatParticipantsInvited` + :param video_chat_participants_invited: Optional. Service message: new participants invited to a video chat + :type video_chat_participants_invited: :class:`telebot.types.VideoChatParticipantsInvited` - :param web_app_data: Optional. Service message: data sent by a Web App - :type web_app_data: :class:`telebot.types.WebAppData` + :param web_app_data: Optional. Service message: data sent by a Web App + :type web_app_data: :class:`telebot.types.WebAppData` - :param reply_markup: Optional. Inline keyboard attached to the message. login_url buttons are represented as - ordinary url buttons. - :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` + :param reply_markup: Optional. Inline keyboard attached to the message. login_url buttons are represented as + ordinary url buttons. + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` - :return: Instance of the class - :rtype: :class:`telebot.types.Message` - """ + :return: Instance of the class + :rtype: :class:`telebot.types.Message` + """ @classmethod def de_json(cls, json_string): if json_string is None: return None From c2ef96580ffb4ffa9946c5f10cde791528f37e48 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Jan 2024 20:28:59 +0400 Subject: [PATCH 110/480] Fix description for pinned/message --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 3da07f7ac..f924d1542 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -982,7 +982,7 @@ class Message(JsonDeserializable): :param pinned_message: Optional. Specified message was pinned. Note that the Message object in this field will not contain further reply_to_message fields even if it is itself a reply. - :type message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` + :type pinned_message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` :param invoice: Optional. Message is an invoice for a payment, information about the invoice. More about payments » :type invoice: :class:`telebot.types.Invoice` From 53920aafe427f31932f099457a2a5de9744f7fbb Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 5 Jan 2024 19:59:15 +0300 Subject: [PATCH 111/480] ReactionTypeCustomEmoji fix --- telebot/types.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 3da07f7ac..aaa91a23c 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8120,7 +8120,7 @@ def to_dict(self) -> dict: return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyUnusedLocal class ReactionTypeCustomEmoji(ReactionType): """ This object represents a custom emoji reaction type. @@ -8130,20 +8130,20 @@ class ReactionTypeCustomEmoji(ReactionType): :param type: Type of the reaction, must be custom_emoji :type type: :obj:`str` - :param custom_emoji: Identifier of the custom emoji - :type custom_emoji: :obj:`str` + :param custom_emoji_id: Identifier of the custom emoji + :type custom_emoji_id: :obj:`str` :return: Instance of the class :rtype: :class:`ReactionTypeCustomEmoji` """ - def __init__(self, custom_emoji: str, **kwargs) -> None: + def __init__(self, custom_emoji_id: str, **kwargs) -> None: super().__init__('custom_emoji') - self.custom_emoji: str = custom_emoji + self.custom_emoji_id: str = custom_emoji_id def to_dict(self) -> dict: json_dict = super().to_dict() - json_dict['custom_emoji'] = self.custom_emoji + json_dict['custom_emoji_id'] = self.custom_emoji_id return json_dict From dcb98c69d74fb45d7d3c877ec68a6d97fb5727c5 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Jan 2024 22:12:36 +0400 Subject: [PATCH 112/480] Fix documentation deprecation in favour of build.os --- .readthedocs.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 0a15ad409..20e759213 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,16 +1,22 @@ -# .readthedocs.yml -# Read the Docs configuration file +# Read the Docs configuration file for Sphinx projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 -# Build documentation in the docs/ directory with Sphinx +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/source/conf.py - -# Optionally build your docs in additional formats such as PDF and ePub -formats: all + # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs + # builder: "dirhtml" + # Fail on all warnings to avoid broken references + # fail_on_warning: true # Optionally set the version of Python and requirements required to build your docs python: From 41c5bb4014f812af5743bdfcad2294d06a42f2e2 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Jan 2024 22:14:30 +0400 Subject: [PATCH 113/480] Update .readthedocs.yml --- .readthedocs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.readthedocs.yml b/.readthedocs.yml index 20e759213..d157652e3 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -18,6 +18,8 @@ sphinx: # Fail on all warnings to avoid broken references # fail_on_warning: true +formats: all + # Optionally set the version of Python and requirements required to build your docs python: version: 3.11 From 7ef91c4bee33b0ce8e0785c0e2801ad74d4d29d0 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 5 Jan 2024 22:20:13 +0400 Subject: [PATCH 114/480] Doc update --- .../locales/en/LC_MESSAGES/async_version.po | 379 +++- .../locales/en/LC_MESSAGES/sync_version.po | 945 +++++---- docs/source/locales/en/LC_MESSAGES/types.po | 1845 +++++++++++++---- .../locales/ru/LC_MESSAGES/async_version.po | 438 +++- .../locales/ru/LC_MESSAGES/sync_version.po | 1039 ++++++---- docs/source/locales/ru/LC_MESSAGES/types.po | 1845 +++++++++++++---- 6 files changed, 4957 insertions(+), 1534 deletions(-) diff --git a/docs/source/locales/en/LC_MESSAGES/async_version.po b/docs/source/locales/en/LC_MESSAGES/async_version.po index cce40349e..fd2679e40 100644 --- a/docs/source/locales/en/LC_MESSAGES/async_version.po +++ b/docs/source/locales/en/LC_MESSAGES/async_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-08 23:07+0500\n" +"POT-Creation-Date: 2024-01-05 22:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -87,12 +87,14 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.callback_query_handler #: telebot.async_telebot.AsyncTeleBot.channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.chat_member_handler #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler #: telebot.async_telebot.AsyncTeleBot.close_forum_topic #: telebot.async_telebot.AsyncTeleBot.close_general_forum_topic #: telebot.async_telebot.AsyncTeleBot.copy_message +#: telebot.async_telebot.AsyncTeleBot.copy_messages #: telebot.async_telebot.AsyncTeleBot.create_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.create_forum_topic #: telebot.async_telebot.AsyncTeleBot.create_invoice_link @@ -102,6 +104,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic #: telebot.async_telebot.AsyncTeleBot.delete_message +#: telebot.async_telebot.AsyncTeleBot.delete_messages #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set @@ -121,6 +124,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.enable_saving_states #: telebot.async_telebot.AsyncTeleBot.export_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.forward_message +#: telebot.async_telebot.AsyncTeleBot.forward_messages #: telebot.async_telebot.AsyncTeleBot.get_chat #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators #: telebot.async_telebot.AsyncTeleBot.get_chat_member @@ -138,6 +142,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos #: telebot.async_telebot.AsyncTeleBot.get_webhook_info #: telebot.async_telebot.AsyncTeleBot.hide_general_forum_topic @@ -145,6 +150,8 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.inline_handler #: telebot.async_telebot.AsyncTeleBot.leave_chat #: telebot.async_telebot.AsyncTeleBot.message_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.pin_chat_message #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler @@ -155,6 +162,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.promote_chat_member #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler @@ -162,11 +170,15 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler #: telebot.async_telebot.AsyncTeleBot.register_inline_handler #: telebot.async_telebot.AsyncTeleBot.register_message_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_handler #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic #: telebot.async_telebot.AsyncTeleBot.reopen_general_forum_topic #: telebot.async_telebot.AsyncTeleBot.reply_to @@ -202,6 +214,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_title #: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights #: telebot.async_telebot.AsyncTeleBot.set_my_description @@ -225,6 +238,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.unhide_general_forum_topic #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message #: telebot.async_telebot.AsyncTeleBot.upload_sticker_file #: telebot.asyncio_filters.TextFilter @@ -298,12 +312,14 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.callback_query_handler #: telebot.async_telebot.AsyncTeleBot.channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.chat_member_handler #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler #: telebot.async_telebot.AsyncTeleBot.close #: telebot.async_telebot.AsyncTeleBot.close_forum_topic #: telebot.async_telebot.AsyncTeleBot.copy_message +#: telebot.async_telebot.AsyncTeleBot.copy_messages #: telebot.async_telebot.AsyncTeleBot.create_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.create_forum_topic #: telebot.async_telebot.AsyncTeleBot.create_invoice_link @@ -313,6 +329,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic #: telebot.async_telebot.AsyncTeleBot.delete_message +#: telebot.async_telebot.AsyncTeleBot.delete_messages #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set @@ -330,6 +347,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.edited_message_handler #: telebot.async_telebot.AsyncTeleBot.export_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.forward_message +#: telebot.async_telebot.AsyncTeleBot.forward_messages #: telebot.async_telebot.AsyncTeleBot.get_chat #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators #: telebot.async_telebot.AsyncTeleBot.get_chat_member @@ -348,6 +366,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos #: telebot.async_telebot.AsyncTeleBot.get_webhook_info #: telebot.async_telebot.AsyncTeleBot.infinity_polling @@ -355,6 +374,8 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.leave_chat #: telebot.async_telebot.AsyncTeleBot.log_out #: telebot.async_telebot.AsyncTeleBot.message_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.pin_chat_message #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler @@ -365,17 +386,22 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.promote_chat_member #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler #: telebot.async_telebot.AsyncTeleBot.register_edited_channel_post_handler #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler #: telebot.async_telebot.AsyncTeleBot.register_inline_handler #: telebot.async_telebot.AsyncTeleBot.register_message_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_handler #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic #: telebot.async_telebot.AsyncTeleBot.reply_to #: telebot.async_telebot.AsyncTeleBot.reset_data @@ -410,6 +436,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_title #: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights #: telebot.async_telebot.AsyncTeleBot.set_my_description @@ -432,6 +459,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message #: telebot.async_telebot.AsyncTeleBot.upload_sticker_file #: telebot.asyncio_filters.TextFilter @@ -443,6 +471,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.add_data:10 #: telebot.async_telebot.AsyncTeleBot.callback_query_handler:9 #: telebot.async_telebot.AsyncTeleBot.channel_post_handler:17 +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler:8 #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:10 #: telebot.async_telebot.AsyncTeleBot.chat_member_handler:11 #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:10 @@ -457,14 +486,19 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.process_new_updates:8 #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:23 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:13 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:26 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:26 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:14 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:14 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:13 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:14 +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:8 #: telebot.async_telebot.AsyncTeleBot.reset_data:9 #: telebot.async_telebot.AsyncTeleBot.set_state:18 #: telebot.async_telebot.AsyncTeleBot.set_update_listener:15 @@ -587,6 +621,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:11 #: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:13 +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:11 msgid "On success, True is returned." msgstr "" @@ -601,6 +636,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.close_forum_topic #: telebot.async_telebot.AsyncTeleBot.copy_message +#: telebot.async_telebot.AsyncTeleBot.copy_messages #: telebot.async_telebot.AsyncTeleBot.create_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.create_forum_topic #: telebot.async_telebot.AsyncTeleBot.create_invoice_link @@ -624,6 +660,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.edit_message_text #: telebot.async_telebot.AsyncTeleBot.export_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.forward_message +#: telebot.async_telebot.AsyncTeleBot.forward_messages #: telebot.async_telebot.AsyncTeleBot.get_chat #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators #: telebot.async_telebot.AsyncTeleBot.get_chat_member @@ -638,6 +675,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos #: telebot.async_telebot.AsyncTeleBot.get_webhook_info #: telebot.async_telebot.AsyncTeleBot.log_out @@ -689,6 +727,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message #: telebot.async_telebot.AsyncTeleBot.upload_sticker_file msgid "Return type" @@ -718,7 +757,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.leave_chat:8 #: telebot.async_telebot.AsyncTeleBot.log_out:11 #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:19 -#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:61 +#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:70 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:14 #: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:61 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:26 @@ -729,6 +768,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_photo:16 #: telebot.async_telebot.AsyncTeleBot.set_chat_title:17 #: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:11 +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction:18 #: telebot.async_telebot.AsyncTeleBot.set_my_commands:18 #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:18 #: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:11 @@ -741,6 +781,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:12 #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:14 +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:12 #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message:15 msgid ":obj:`bool`" msgstr "" @@ -980,6 +1021,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_member:12 #: telebot.async_telebot.AsyncTeleBot.decline_chat_join_request:11 #: telebot.async_telebot.AsyncTeleBot.get_chat_member:8 +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:8 #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:6 #: telebot.async_telebot.AsyncTeleBot.promote_chat_member:11 #: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:14 @@ -995,7 +1037,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.delete_my_commands:16 #: telebot.async_telebot.AsyncTeleBot.log_out:10 #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:18 -#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:60 +#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:69 #: telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:17 #: telebot.async_telebot.AsyncTeleBot.set_chat_description:13 #: telebot.async_telebot.AsyncTeleBot.set_chat_menu_button:14 @@ -1050,6 +1092,7 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.ban_chat_member:24 #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set:10 #: telebot.async_telebot.AsyncTeleBot.delete_message:22 +#: telebot.async_telebot.AsyncTeleBot.delete_messages:14 #: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:6 #: telebot.async_telebot.AsyncTeleBot.delete_webhook:12 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:25 @@ -1079,13 +1122,16 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.close_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.close_general_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.copy_message:5 +#: telebot.async_telebot.AsyncTeleBot.copy_messages:3 #: telebot.async_telebot.AsyncTeleBot.create_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.delete_message:13 +#: telebot.async_telebot.AsyncTeleBot.delete_messages:8 #: telebot.async_telebot.AsyncTeleBot.edit_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.edit_general_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.edit_message_live_location:13 #: telebot.async_telebot.AsyncTeleBot.forward_message:8 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:3 #: telebot.async_telebot.AsyncTeleBot.hide_general_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:7 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:7 @@ -1127,18 +1173,22 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.callback_query_handler:4 #: telebot.async_telebot.AsyncTeleBot.channel_post_handler:10 +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler:4 #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:5 #: telebot.async_telebot.AsyncTeleBot.chat_member_handler:6 #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:5 #: telebot.async_telebot.AsyncTeleBot.edited_channel_post_handler:10 #: telebot.async_telebot.AsyncTeleBot.edited_message_handler:11 #: telebot.async_telebot.AsyncTeleBot.inline_handler:4 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler:4 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler:4 #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler:5 #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler:5 #: telebot.async_telebot.AsyncTeleBot.poll_handler:4 #: telebot.async_telebot.AsyncTeleBot.pre_checkout_query_handler:4 #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:15 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:6 @@ -1146,17 +1196,22 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:15 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:15 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:6 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:6 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:6 +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:4 #: telebot.async_telebot.AsyncTeleBot.shipping_query_handler:4 msgid "Function executed as a filter" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.callback_query_handler:7 #: telebot.async_telebot.AsyncTeleBot.channel_post_handler:16 +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler:7 #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:8 #: telebot.async_telebot.AsyncTeleBot.chat_member_handler:9 #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:8 @@ -1164,12 +1219,15 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.edited_message_handler:20 #: telebot.async_telebot.AsyncTeleBot.inline_handler:7 #: telebot.async_telebot.AsyncTeleBot.message_handler:50 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler:7 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler:7 #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler:8 #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler:8 #: telebot.async_telebot.AsyncTeleBot.poll_handler:7 #: telebot.async_telebot.AsyncTeleBot.pre_checkout_query_handler:7 #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:21 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:11 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:12 @@ -1177,11 +1235,15 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:24 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:24 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:12 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:11 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:11 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:12 +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:7 #: telebot.async_telebot.AsyncTeleBot.shipping_query_handler:7 msgid "Optional keyword arguments(custom filters)" msgstr "" @@ -1218,6 +1280,12 @@ msgstr "" msgid "Supported message content types. Must be a list. Defaults to ['text']." msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.chat_boost_handler:1 +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostUpdated` object." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:1 msgid "" "Handles a request to join the chat has been sent. The bot must have the " @@ -1293,6 +1361,7 @@ msgid "" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.copy_message:1 +#: telebot.async_telebot.AsyncTeleBot.copy_messages:1 msgid "Use this method to copy messages of any kind." msgstr "" @@ -1301,7 +1370,9 @@ msgid "Telegram documentation: https://core.telegram.org/bots/api#copymessage" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.copy_message:8 +#: telebot.async_telebot.AsyncTeleBot.copy_messages:6 #: telebot.async_telebot.AsyncTeleBot.forward_message:11 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:6 msgid "" "Unique identifier for the chat where the original message was sent (or " "channel username in the format @channelusername)" @@ -1462,8 +1533,6 @@ msgid "Identifier of a message thread, in which the message will be sent" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.copy_message:45 -#: telebot.async_telebot.AsyncTeleBot.forward_message:26 -#: telebot.async_telebot.AsyncTeleBot.reply_to:11 #: telebot.async_telebot.AsyncTeleBot.send_animation:66 #: telebot.async_telebot.AsyncTeleBot.send_audio:66 #: telebot.async_telebot.AsyncTeleBot.send_contact:44 @@ -1472,6 +1541,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.send_game:32 #: telebot.async_telebot.AsyncTeleBot.send_invoice:101 #: telebot.async_telebot.AsyncTeleBot.send_location:49 +#: telebot.async_telebot.AsyncTeleBot.send_media_group:30 #: telebot.async_telebot.AsyncTeleBot.send_message:46 #: telebot.async_telebot.AsyncTeleBot.send_photo:48 #: telebot.async_telebot.AsyncTeleBot.send_poll:70 @@ -1480,25 +1550,53 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.send_video:67 #: telebot.async_telebot.AsyncTeleBot.send_video_note:51 #: telebot.async_telebot.AsyncTeleBot.send_voice:49 -msgid "On success, the sent Message is returned." +msgid "Reply parameters." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.copy_message:46 -#: telebot.async_telebot.AsyncTeleBot.forward_message:27 -#: telebot.async_telebot.AsyncTeleBot.reply_to:12 -#: telebot.async_telebot.AsyncTeleBot.send_animation:67 -#: telebot.async_telebot.AsyncTeleBot.send_audio:67 -#: telebot.async_telebot.AsyncTeleBot.send_contact:45 -#: telebot.async_telebot.AsyncTeleBot.send_dice:36 -#: telebot.async_telebot.AsyncTeleBot.send_document:60 -#: telebot.async_telebot.AsyncTeleBot.send_location:50 -#: telebot.async_telebot.AsyncTeleBot.send_message:47 -#: telebot.async_telebot.AsyncTeleBot.send_photo:49 -#: telebot.async_telebot.AsyncTeleBot.send_sticker:43 -#: telebot.async_telebot.AsyncTeleBot.send_venue:58 -#: telebot.async_telebot.AsyncTeleBot.send_video:68 -#: telebot.async_telebot.AsyncTeleBot.send_video_note:52 -msgid ":class:`telebot.types.Message`" +#: of telebot.async_telebot.AsyncTeleBot.copy_message:48 +msgid "On success, the MessageId of the sent message is returned." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_message:49 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:22 +msgid ":class:`telebot.types.MessageID`" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:9 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:9 +msgid "Message identifiers in the chat specified in from_chat_id" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:12 +#: telebot.async_telebot.AsyncTeleBot.forward_message:5 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:12 +msgid "" +"Sends the message silently. Users will receive a notification with no " +"sound" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:15 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:15 +#: telebot.async_telebot.AsyncTeleBot.send_media_group:27 +msgid "Identifier of a message thread, in which the messages will be sent" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:18 +#: telebot.async_telebot.AsyncTeleBot.forward_message:17 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:18 +msgid "Protects the contents of the forwarded message from forwarding and saving" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:21 +msgid "Pass True to copy the messages without their captions" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:24 +msgid "On success, an array of MessageId of the sent messages is returned." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:25 +msgid ":obj:`list` of :class:`telebot.types.MessageID`" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.create_chat_invite_link:1 @@ -1888,6 +1986,22 @@ msgstr "" msgid "Identifier of the message to delete" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.delete_messages:1 +msgid "" +"Use this method to delete multiple messages in a chat. The number of " +"messages to be deleted must not exceed 100. If the chat is a private " +"chat, the user must be an administrator of the chat for this to work and " +"must have the appropriate admin rights. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.delete_messages:6 +msgid "Telegram documentation: https://core.telegram.org/bots/api#deletemessages" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.delete_messages:11 +msgid "Identifiers of the messages to be deleted" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.delete_my_commands:1 msgid "" "Use this method to delete the list of the bot's commands for the given " @@ -2093,7 +2207,7 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.edit_message_caption:26 #: telebot.async_telebot.AsyncTeleBot.edit_message_media:22 #: telebot.async_telebot.AsyncTeleBot.edit_message_reply_markup:17 -#: telebot.async_telebot.AsyncTeleBot.edit_message_text:29 +#: telebot.async_telebot.AsyncTeleBot.edit_message_text:32 msgid "" "On success, if edited message is sent by the bot, the edited Message is " "returned, otherwise True is returned." @@ -2222,7 +2336,7 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.edit_message_media:23 #: telebot.async_telebot.AsyncTeleBot.edit_message_reply_markup:18 -#: telebot.async_telebot.AsyncTeleBot.edit_message_text:30 +#: telebot.async_telebot.AsyncTeleBot.edit_message_text:33 #: telebot.async_telebot.AsyncTeleBot.set_game_score:27 msgid ":obj:`types.Message` or :obj:`bool`" msgstr "" @@ -2265,6 +2379,12 @@ msgstr "" msgid "Disables link previews for links in this message" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.edit_message_text:29 +msgid "" +"A JSON-serialized object for options used to automatically generate " +"Telegram link previews for messages." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.edited_channel_post_handler:1 msgid "" "Handles new version of a channel post that is known to the bot and was " @@ -2320,6 +2440,7 @@ msgid "exported invite link as String on success." msgstr "" #: of telebot.async_telebot.AsyncTeleBot.forward_message:1 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:1 msgid "Use this method to forward messages of any kind." msgstr "" @@ -2327,16 +2448,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#forwardmessage" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.forward_message:5 -msgid "" -"Sends the message silently. Users will receive a notification with no " -"sound" -msgstr "" - -#: of telebot.async_telebot.AsyncTeleBot.forward_message:17 -msgid "Protects the contents of the forwarded message from forwarding and saving" -msgstr "" - #: of telebot.async_telebot.AsyncTeleBot.forward_message:23 #: telebot.async_telebot.AsyncTeleBot.send_message:43 msgid "" @@ -2344,6 +2455,45 @@ msgid "" " forum supergroups only" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.forward_message:26 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:21 +#: telebot.async_telebot.AsyncTeleBot.reply_to:11 +#: telebot.async_telebot.AsyncTeleBot.send_animation:69 +#: telebot.async_telebot.AsyncTeleBot.send_audio:69 +#: telebot.async_telebot.AsyncTeleBot.send_contact:47 +#: telebot.async_telebot.AsyncTeleBot.send_dice:38 +#: telebot.async_telebot.AsyncTeleBot.send_document:62 +#: telebot.async_telebot.AsyncTeleBot.send_game:35 +#: telebot.async_telebot.AsyncTeleBot.send_invoice:104 +#: telebot.async_telebot.AsyncTeleBot.send_location:52 +#: telebot.async_telebot.AsyncTeleBot.send_message:52 +#: telebot.async_telebot.AsyncTeleBot.send_photo:51 +#: telebot.async_telebot.AsyncTeleBot.send_poll:73 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:45 +#: telebot.async_telebot.AsyncTeleBot.send_venue:60 +#: telebot.async_telebot.AsyncTeleBot.send_video:70 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:54 +#: telebot.async_telebot.AsyncTeleBot.send_voice:52 +msgid "On success, the sent Message is returned." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.forward_message:27 +#: telebot.async_telebot.AsyncTeleBot.reply_to:12 +#: telebot.async_telebot.AsyncTeleBot.send_animation:70 +#: telebot.async_telebot.AsyncTeleBot.send_audio:70 +#: telebot.async_telebot.AsyncTeleBot.send_contact:48 +#: telebot.async_telebot.AsyncTeleBot.send_dice:39 +#: telebot.async_telebot.AsyncTeleBot.send_document:63 +#: telebot.async_telebot.AsyncTeleBot.send_location:53 +#: telebot.async_telebot.AsyncTeleBot.send_message:53 +#: telebot.async_telebot.AsyncTeleBot.send_photo:52 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:46 +#: telebot.async_telebot.AsyncTeleBot.send_venue:61 +#: telebot.async_telebot.AsyncTeleBot.send_video:71 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:55 +msgid ":class:`telebot.types.Message`" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.get_chat:1 msgid "" "Use this method to get up to date information about the chat (current " @@ -2359,6 +2509,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators:7 #: telebot.async_telebot.AsyncTeleBot.get_chat_member_count:5 #: telebot.async_telebot.AsyncTeleBot.leave_chat:5 +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction:5 msgid "" "Unique identifier for the target chat or username of the target " "supergroup or channel (in the format @channelusername)" @@ -2740,6 +2891,36 @@ msgstr "" msgid ":obj:`list` of :class:`telebot.types.Update`" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:1 +msgid "" +"Use this method to get the list of boosts added to a chat by a user. " +"Requires administrator rights in the chat. Returns a UserChatBoosts " +"object." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getuserchatboosts" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:5 +#: telebot.async_telebot.AsyncTeleBot.send_chat_action:10 +#: telebot.async_telebot.AsyncTeleBot.send_contact:5 +#: telebot.async_telebot.AsyncTeleBot.send_poll:6 +#: telebot.async_telebot.AsyncTeleBot.send_venue:5 +#: telebot.async_telebot.AsyncTeleBot.stop_poll:5 +msgid "Unique identifier for the target chat or username of the target channel" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:11 +msgid "On success, a UserChatBoosts object is returned." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:12 +msgid ":class:`telebot.types.UserChatBoosts`" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:1 msgid "" "Use this method to get a list of profile pictures for a user. Returns a " @@ -2942,6 +3123,19 @@ msgstr "" msgid "decorated function" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler:1 +msgid "" +"Handles new incoming message reaction count. As a parameter to the " +"decorator function, it passes " +":class:`telebot.types.MessageReactionCountUpdated` object." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.message_reaction_handler:1 +msgid "" +"Handles new incoming message reaction. As a parameter to the decorator " +"function, it passes :class:`telebot.types.MessageReactionUpdated` object." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.my_chat_member_handler:1 msgid "" "Handles update in a status of a bot. For private chats, this update is " @@ -3128,12 +3322,25 @@ msgid "" "forum topics, supergroups only" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:60 +msgid "Pass True if the administrator can create the channel's stories" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:63 +msgid "Pass True if the administrator can edit the channel's stories" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:66 +msgid "Pass True if the administrator can delete the channel's stories" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:1 msgid "Registers callback query handler." msgstr "" #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:3 @@ -3141,16 +3348,20 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:3 msgid "function to be called" msgstr "" #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:18 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:9 @@ -3158,10 +3369,13 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:21 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:21 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:9 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:8 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:9 msgid "" "True if you need to pass TeleBot instance to handler(useful for " @@ -3185,6 +3399,10 @@ msgstr "" msgid "Regular expression" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:1 +msgid "Registers chat boost handler." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:1 msgid "Registers chat join request handler." msgstr "" @@ -3225,6 +3443,15 @@ msgstr "" msgid "List of chat types" msgstr "" +#: of +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:1 +msgid "Registers message reaction count handler." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:1 +msgid "Registers message reaction handler." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:1 msgid "Registers my chat member handler." msgstr "" @@ -3241,6 +3468,10 @@ msgstr "" msgid "Registers pre-checkout request handler." msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:1 +msgid "Registers removed chat boost handler." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:1 msgid "Registers shipping query handler." msgstr "" @@ -3249,6 +3480,12 @@ msgstr "" msgid "Alternative for delete_webhook but uses set_webhook" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:1 +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostRemoved` object." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:1 msgid "" "Use this method to reopen a closed topic in a forum supergroup chat. The " @@ -3670,14 +3907,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendchataction" msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.send_chat_action:10 -#: telebot.async_telebot.AsyncTeleBot.send_contact:5 -#: telebot.async_telebot.AsyncTeleBot.send_poll:6 -#: telebot.async_telebot.AsyncTeleBot.send_venue:5 -#: telebot.async_telebot.AsyncTeleBot.stop_poll:5 -msgid "Unique identifier for the target chat or username of the target channel" -msgstr "" - #: of telebot.async_telebot.AsyncTeleBot.send_chat_action:13 msgid "" "Type of action to broadcast. Choose one, depending on what the user is " @@ -3843,9 +4072,9 @@ msgstr "" msgid "Identifier of the thread to which the message will be sent." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.send_game:33 -#: telebot.async_telebot.AsyncTeleBot.send_invoice:102 -#: telebot.async_telebot.AsyncTeleBot.send_poll:71 +#: of telebot.async_telebot.AsyncTeleBot.send_game:36 +#: telebot.async_telebot.AsyncTeleBot.send_invoice:105 +#: telebot.async_telebot.AsyncTeleBot.send_poll:74 msgid ":obj:`types.Message`" msgstr "" @@ -3953,11 +4182,7 @@ msgid "" "sound." msgstr "" -#: of telebot.async_telebot.AsyncTeleBot.send_media_group:27 -msgid "Identifier of a message thread, in which the messages will be sent" -msgstr "" - -#: of telebot.async_telebot.AsyncTeleBot.send_media_group:30 +#: of telebot.async_telebot.AsyncTeleBot.send_media_group:33 msgid "On success, an array of Messages that were sent is returned." msgstr "" @@ -3992,6 +4217,10 @@ msgid "" "target user" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.send_message:49 +msgid "Options for previewing links." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_photo:1 msgid "Use this method to send photos. On success, the sent Message is returned." msgstr "" @@ -4471,6 +4700,35 @@ msgid "" "Message, otherwise returns True." msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:1 +msgid "" +"Use this method to set a reaction to a message in a chat. The bot must be" +" an administrator in the chat for this to work and must have the " +"appropriate admin rights. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmessagereaction" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:8 +msgid "Identifier of the message to set reaction to" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:11 +msgid "" +"New list of reaction types to set on the message. Currently, as non-" +"premium users, bots can set up to one reaction per message. A custom " +"emoji reaction can be used if it is either already present on the message" +" or explicitly allowed by chat administrators." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:15 +msgid "Pass True to set the reaction with a big animation" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_my_commands:1 msgid "Use this method to change the list of the bot's commands." msgstr "" @@ -4952,6 +5210,27 @@ msgstr "" msgid "Identifier of the topic" msgstr "" +#: of +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:1 +msgid "" +"Use this method to clear the list of pinned messages in a General forum " +"topic. The bot must be an administrator in the chat for this to work and " +"must have the can_pin_messages administrator right in the supergroup. " +"Returns True on success." +msgstr "" + +#: of +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:6 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages" +msgstr "" + +#: of +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:8 +msgid "Unique identifier for the target chat or username of chat" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.unpin_chat_message:1 msgid "" "Use this method to unpin specific pinned message in a supergroup chat. " diff --git a/docs/source/locales/en/LC_MESSAGES/sync_version.po b/docs/source/locales/en/LC_MESSAGES/sync_version.po index 13aa6b3cf..30d0fb92f 100644 --- a/docs/source/locales/en/LC_MESSAGES/sync_version.po +++ b/docs/source/locales/en/LC_MESSAGES/sync_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-08 23:07+0500\n" +"POT-Creation-Date: 2024-01-05 22:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -98,7 +98,7 @@ msgstr "" #: telebot.TeleBot.answer_shipping_query telebot.TeleBot.answer_web_app_query #: telebot.TeleBot.approve_chat_join_request telebot.TeleBot.ban_chat_member #: telebot.TeleBot.ban_chat_sender_chat telebot.TeleBot.callback_query_handler -#: telebot.TeleBot.channel_post_handler +#: telebot.TeleBot.channel_post_handler telebot.TeleBot.chat_boost_handler #: telebot.TeleBot.chat_join_request_handler #: telebot.TeleBot.chat_member_handler telebot.TeleBot.chosen_inline_handler #: telebot.TeleBot.clear_reply_handlers @@ -106,16 +106,17 @@ msgstr "" #: telebot.TeleBot.clear_step_handler #: telebot.TeleBot.clear_step_handler_by_chat_id #: telebot.TeleBot.close_forum_topic telebot.TeleBot.close_general_forum_topic -#: telebot.TeleBot.copy_message telebot.TeleBot.create_chat_invite_link -#: telebot.TeleBot.create_forum_topic telebot.TeleBot.create_invoice_link -#: telebot.TeleBot.create_new_sticker_set +#: telebot.TeleBot.copy_message telebot.TeleBot.copy_messages +#: telebot.TeleBot.create_chat_invite_link telebot.TeleBot.create_forum_topic +#: telebot.TeleBot.create_invoice_link telebot.TeleBot.create_new_sticker_set #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic -#: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands -#: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook -#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link -#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_general_forum_topic +#: telebot.TeleBot.delete_message telebot.TeleBot.delete_messages +#: telebot.TeleBot.delete_my_commands telebot.TeleBot.delete_state +#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_sticker_set +#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file +#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic +#: telebot.TeleBot.edit_general_forum_topic #: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup @@ -125,9 +126,10 @@ msgstr "" #: telebot.TeleBot.enable_save_next_step_handlers #: telebot.TeleBot.enable_save_reply_handlers #: telebot.TeleBot.enable_saving_states telebot.TeleBot.export_chat_invite_link -#: telebot.TeleBot.forward_message telebot.TeleBot.get_chat -#: telebot.TeleBot.get_chat_administrators telebot.TeleBot.get_chat_member -#: telebot.TeleBot.get_chat_member_count telebot.TeleBot.get_chat_menu_button +#: telebot.TeleBot.forward_message telebot.TeleBot.forward_messages +#: telebot.TeleBot.get_chat telebot.TeleBot.get_chat_administrators +#: telebot.TeleBot.get_chat_member telebot.TeleBot.get_chat_member_count +#: telebot.TeleBot.get_chat_menu_button #: telebot.TeleBot.get_custom_emoji_stickers telebot.TeleBot.get_file #: telebot.TeleBot.get_file_url telebot.TeleBot.get_game_high_scores #: telebot.TeleBot.get_my_commands @@ -135,17 +137,20 @@ msgstr "" #: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name #: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state #: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates -#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info -#: telebot.TeleBot.hide_general_forum_topic telebot.TeleBot.infinity_polling -#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat -#: telebot.TeleBot.load_next_step_handlers telebot.TeleBot.load_reply_handlers -#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.get_user_chat_boosts telebot.TeleBot.get_user_profile_photos +#: telebot.TeleBot.get_webhook_info telebot.TeleBot.hide_general_forum_topic +#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler +#: telebot.TeleBot.leave_chat telebot.TeleBot.load_next_step_handlers +#: telebot.TeleBot.load_reply_handlers telebot.TeleBot.message_handler +#: telebot.TeleBot.message_reaction_count_handler +#: telebot.TeleBot.message_reaction_handler telebot.TeleBot.middleware_handler #: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message #: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler #: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.process_new_updates telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler +#: telebot.TeleBot.register_chat_boost_handler #: telebot.TeleBot.register_chat_join_request_handler #: telebot.TeleBot.register_chat_member_handler #: telebot.TeleBot.register_chosen_inline_handler @@ -155,6 +160,8 @@ msgstr "" #: telebot.TeleBot.register_for_reply_by_message_id #: telebot.TeleBot.register_inline_handler #: telebot.TeleBot.register_message_handler +#: telebot.TeleBot.register_message_reaction_count_handler +#: telebot.TeleBot.register_message_reaction_handler #: telebot.TeleBot.register_middleware_handler #: telebot.TeleBot.register_my_chat_member_handler #: telebot.TeleBot.register_next_step_handler @@ -162,7 +169,9 @@ msgstr "" #: telebot.TeleBot.register_poll_answer_handler #: telebot.TeleBot.register_poll_handler #: telebot.TeleBot.register_pre_checkout_query_handler +#: telebot.TeleBot.register_removed_chat_boost_handler #: telebot.TeleBot.register_shipping_query_handler +#: telebot.TeleBot.removed_chat_boost_handler #: telebot.TeleBot.reopen_forum_topic #: telebot.TeleBot.reopen_general_forum_topic telebot.TeleBot.reply_to #: telebot.TeleBot.reset_data telebot.TeleBot.restrict_chat_member @@ -175,13 +184,15 @@ msgstr "" #: telebot.TeleBot.send_media_group telebot.TeleBot.send_message #: telebot.TeleBot.send_photo telebot.TeleBot.send_poll #: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_voice +#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note +#: telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail -#: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands +#: telebot.TeleBot.set_game_score telebot.TeleBot.set_message_reaction +#: telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights #: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name #: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state @@ -197,6 +208,7 @@ msgstr "" #: telebot.TeleBot.unhide_general_forum_topic #: telebot.TeleBot.unpin_all_chat_messages #: telebot.TeleBot.unpin_all_forum_topic_messages +#: telebot.TeleBot.unpin_all_general_forum_topic_messages #: telebot.TeleBot.unpin_chat_message telebot.TeleBot.upload_sticker_file #: telebot.custom_filters.TextFilter msgid "Parameters" @@ -312,7 +324,7 @@ msgstr "" #: telebot.TeleBot.answer_shipping_query telebot.TeleBot.answer_web_app_query #: telebot.TeleBot.approve_chat_join_request telebot.TeleBot.ban_chat_member #: telebot.TeleBot.ban_chat_sender_chat telebot.TeleBot.callback_query_handler -#: telebot.TeleBot.channel_post_handler +#: telebot.TeleBot.channel_post_handler telebot.TeleBot.chat_boost_handler #: telebot.TeleBot.chat_join_request_handler #: telebot.TeleBot.chat_member_handler telebot.TeleBot.chosen_inline_handler #: telebot.TeleBot.clear_reply_handlers @@ -320,15 +332,17 @@ msgstr "" #: telebot.TeleBot.clear_step_handler #: telebot.TeleBot.clear_step_handler_by_chat_id telebot.TeleBot.close #: telebot.TeleBot.close_forum_topic telebot.TeleBot.copy_message -#: telebot.TeleBot.create_chat_invite_link telebot.TeleBot.create_forum_topic -#: telebot.TeleBot.create_invoice_link telebot.TeleBot.create_new_sticker_set +#: telebot.TeleBot.copy_messages telebot.TeleBot.create_chat_invite_link +#: telebot.TeleBot.create_forum_topic telebot.TeleBot.create_invoice_link +#: telebot.TeleBot.create_new_sticker_set #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic -#: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands -#: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook -#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link -#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_message_caption +#: telebot.TeleBot.delete_message telebot.TeleBot.delete_messages +#: telebot.TeleBot.delete_my_commands telebot.TeleBot.delete_state +#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_sticker_set +#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file +#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic +#: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text @@ -336,9 +350,9 @@ msgstr "" #: telebot.TeleBot.edited_message_handler #: telebot.TeleBot.enable_save_next_step_handlers #: telebot.TeleBot.export_chat_invite_link telebot.TeleBot.forward_message -#: telebot.TeleBot.get_chat telebot.TeleBot.get_chat_administrators -#: telebot.TeleBot.get_chat_member telebot.TeleBot.get_chat_member_count -#: telebot.TeleBot.get_chat_menu_button +#: telebot.TeleBot.forward_messages telebot.TeleBot.get_chat +#: telebot.TeleBot.get_chat_administrators telebot.TeleBot.get_chat_member +#: telebot.TeleBot.get_chat_member_count telebot.TeleBot.get_chat_menu_button #: telebot.TeleBot.get_custom_emoji_stickers telebot.TeleBot.get_file #: telebot.TeleBot.get_file_url telebot.TeleBot.get_forum_topic_icon_stickers #: telebot.TeleBot.get_game_high_scores telebot.TeleBot.get_my_commands @@ -346,16 +360,19 @@ msgstr "" #: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name #: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state #: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates -#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info -#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler -#: telebot.TeleBot.leave_chat telebot.TeleBot.log_out -#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.get_user_chat_boosts telebot.TeleBot.get_user_profile_photos +#: telebot.TeleBot.get_webhook_info telebot.TeleBot.infinity_polling +#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat +#: telebot.TeleBot.log_out telebot.TeleBot.message_handler +#: telebot.TeleBot.message_reaction_count_handler +#: telebot.TeleBot.message_reaction_handler telebot.TeleBot.middleware_handler #: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message #: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler #: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler +#: telebot.TeleBot.register_chat_boost_handler #: telebot.TeleBot.register_chat_join_request_handler #: telebot.TeleBot.register_chosen_inline_handler #: telebot.TeleBot.register_edited_channel_post_handler @@ -364,6 +381,8 @@ msgstr "" #: telebot.TeleBot.register_for_reply_by_message_id #: telebot.TeleBot.register_inline_handler #: telebot.TeleBot.register_message_handler +#: telebot.TeleBot.register_message_reaction_count_handler +#: telebot.TeleBot.register_message_reaction_handler #: telebot.TeleBot.register_middleware_handler #: telebot.TeleBot.register_my_chat_member_handler #: telebot.TeleBot.register_next_step_handler @@ -371,25 +390,28 @@ msgstr "" #: telebot.TeleBot.register_poll_answer_handler #: telebot.TeleBot.register_poll_handler #: telebot.TeleBot.register_pre_checkout_query_handler +#: telebot.TeleBot.register_removed_chat_boost_handler #: telebot.TeleBot.register_shipping_query_handler -#: telebot.TeleBot.remove_webhook telebot.TeleBot.reopen_forum_topic -#: telebot.TeleBot.reply_to telebot.TeleBot.reset_data -#: telebot.TeleBot.restrict_chat_member telebot.TeleBot.retrieve_data -#: telebot.TeleBot.revoke_chat_invite_link telebot.TeleBot.send_animation -#: telebot.TeleBot.send_audio telebot.TeleBot.send_chat_action -#: telebot.TeleBot.send_contact telebot.TeleBot.send_dice -#: telebot.TeleBot.send_document telebot.TeleBot.send_game -#: telebot.TeleBot.send_invoice telebot.TeleBot.send_location -#: telebot.TeleBot.send_media_group telebot.TeleBot.send_message -#: telebot.TeleBot.send_photo telebot.TeleBot.send_poll -#: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_voice +#: telebot.TeleBot.remove_webhook telebot.TeleBot.removed_chat_boost_handler +#: telebot.TeleBot.reopen_forum_topic telebot.TeleBot.reply_to +#: telebot.TeleBot.reset_data telebot.TeleBot.restrict_chat_member +#: telebot.TeleBot.retrieve_data telebot.TeleBot.revoke_chat_invite_link +#: telebot.TeleBot.send_animation telebot.TeleBot.send_audio +#: telebot.TeleBot.send_chat_action telebot.TeleBot.send_contact +#: telebot.TeleBot.send_dice telebot.TeleBot.send_document +#: telebot.TeleBot.send_game telebot.TeleBot.send_invoice +#: telebot.TeleBot.send_location telebot.TeleBot.send_media_group +#: telebot.TeleBot.send_message telebot.TeleBot.send_photo +#: telebot.TeleBot.send_poll telebot.TeleBot.send_sticker +#: telebot.TeleBot.send_venue telebot.TeleBot.send_video +#: telebot.TeleBot.send_video_note telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail -#: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands +#: telebot.TeleBot.set_game_score telebot.TeleBot.set_message_reaction +#: telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights #: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name #: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state @@ -403,6 +425,7 @@ msgstr "" #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat #: telebot.TeleBot.unpin_all_chat_messages #: telebot.TeleBot.unpin_all_forum_topic_messages +#: telebot.TeleBot.unpin_all_general_forum_topic_messages #: telebot.TeleBot.unpin_chat_message telebot.TeleBot.upload_sticker_file #: telebot.TeleBot.user telebot.custom_filters.TextFilter #: telebot.ext.sync.webhooks.SyncWebhookListener.run_app @@ -410,7 +433,7 @@ msgid "Returns" msgstr "" #: of telebot.TeleBot.add_data:10 telebot.TeleBot.callback_query_handler:9 -#: telebot.TeleBot.channel_post_handler:18 +#: telebot.TeleBot.channel_post_handler:18 telebot.TeleBot.chat_boost_handler:8 #: telebot.TeleBot.chat_join_request_handler:10 #: telebot.TeleBot.chat_member_handler:11 #: telebot.TeleBot.chosen_inline_handler:10 @@ -425,21 +448,26 @@ msgstr "" #: telebot.TeleBot.pre_checkout_query_handler:9 #: telebot.TeleBot.register_callback_query_handler:14 #: telebot.TeleBot.register_channel_post_handler:23 +#: telebot.TeleBot.register_chat_boost_handler:13 #: telebot.TeleBot.register_chat_join_request_handler:14 #: telebot.TeleBot.register_chosen_inline_handler:14 #: telebot.TeleBot.register_edited_message_handler:26 #: telebot.TeleBot.register_for_reply:15 #: telebot.TeleBot.register_for_reply_by_message_id:15 #: telebot.TeleBot.register_message_handler:26 +#: telebot.TeleBot.register_message_reaction_count_handler:14 +#: telebot.TeleBot.register_message_reaction_handler:14 #: telebot.TeleBot.register_middleware_handler:18 #: telebot.TeleBot.register_my_chat_member_handler:14 #: telebot.TeleBot.register_next_step_handler:15 #: telebot.TeleBot.register_next_step_handler_by_chat_id:15 #: telebot.TeleBot.register_poll_answer_handler:14 #: telebot.TeleBot.register_poll_handler:14 +#: telebot.TeleBot.register_removed_chat_boost_handler:13 #: telebot.TeleBot.register_shipping_query_handler:14 -#: telebot.TeleBot.reset_data:9 telebot.TeleBot.set_state:18 -#: telebot.TeleBot.setup_middleware:5 telebot.TeleBot.shipping_query_handler:9 +#: telebot.TeleBot.removed_chat_boost_handler:8 telebot.TeleBot.reset_data:9 +#: telebot.TeleBot.set_state:18 telebot.TeleBot.setup_middleware:5 +#: telebot.TeleBot.shipping_query_handler:9 #: telebot.custom_filters.TextFilter:22 #: telebot.ext.sync.webhooks.SyncWebhookListener.run_app:4 msgid "None" @@ -530,6 +558,7 @@ msgstr "" #: telebot.TeleBot.set_sticker_position_in_set:11 #: telebot.TeleBot.set_sticker_set_thumbnail:15 #: telebot.TeleBot.unpin_all_forum_topic_messages:13 +#: telebot.TeleBot.unpin_all_general_forum_topic_messages:11 msgid "On success, True is returned." msgstr "" @@ -539,9 +568,9 @@ msgstr "" #: telebot.TeleBot.answer_shipping_query telebot.TeleBot.answer_web_app_query #: telebot.TeleBot.approve_chat_join_request telebot.TeleBot.ban_chat_member #: telebot.TeleBot.ban_chat_sender_chat telebot.TeleBot.close_forum_topic -#: telebot.TeleBot.copy_message telebot.TeleBot.create_chat_invite_link -#: telebot.TeleBot.create_forum_topic telebot.TeleBot.create_invoice_link -#: telebot.TeleBot.create_new_sticker_set +#: telebot.TeleBot.copy_message telebot.TeleBot.copy_messages +#: telebot.TeleBot.create_chat_invite_link telebot.TeleBot.create_forum_topic +#: telebot.TeleBot.create_invoice_link telebot.TeleBot.create_new_sticker_set #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands @@ -552,28 +581,30 @@ msgstr "" #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text telebot.TeleBot.export_chat_invite_link -#: telebot.TeleBot.forward_message telebot.TeleBot.get_chat -#: telebot.TeleBot.get_chat_administrators telebot.TeleBot.get_chat_member -#: telebot.TeleBot.get_chat_member_count telebot.TeleBot.get_chat_menu_button +#: telebot.TeleBot.forward_message telebot.TeleBot.forward_messages +#: telebot.TeleBot.get_chat telebot.TeleBot.get_chat_administrators +#: telebot.TeleBot.get_chat_member telebot.TeleBot.get_chat_member_count +#: telebot.TeleBot.get_chat_menu_button #: telebot.TeleBot.get_custom_emoji_stickers telebot.TeleBot.get_file_url #: telebot.TeleBot.get_forum_topic_icon_stickers #: telebot.TeleBot.get_game_high_scores telebot.TeleBot.get_my_commands #: telebot.TeleBot.get_my_default_administrator_rights #: telebot.TeleBot.get_state telebot.TeleBot.get_sticker_set -#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_profile_photos -#: telebot.TeleBot.get_webhook_info telebot.TeleBot.log_out -#: telebot.TeleBot.pin_chat_message telebot.TeleBot.promote_chat_member -#: telebot.TeleBot.remove_webhook telebot.TeleBot.reopen_forum_topic -#: telebot.TeleBot.reply_to telebot.TeleBot.restrict_chat_member -#: telebot.TeleBot.retrieve_data telebot.TeleBot.revoke_chat_invite_link -#: telebot.TeleBot.send_animation telebot.TeleBot.send_audio -#: telebot.TeleBot.send_chat_action telebot.TeleBot.send_contact -#: telebot.TeleBot.send_dice telebot.TeleBot.send_document -#: telebot.TeleBot.send_game telebot.TeleBot.send_invoice -#: telebot.TeleBot.send_location telebot.TeleBot.send_media_group -#: telebot.TeleBot.send_message telebot.TeleBot.send_photo -#: telebot.TeleBot.send_poll telebot.TeleBot.send_sticker -#: telebot.TeleBot.send_venue telebot.TeleBot.send_video +#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_chat_boosts +#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info +#: telebot.TeleBot.log_out telebot.TeleBot.pin_chat_message +#: telebot.TeleBot.promote_chat_member telebot.TeleBot.remove_webhook +#: telebot.TeleBot.reopen_forum_topic telebot.TeleBot.reply_to +#: telebot.TeleBot.restrict_chat_member telebot.TeleBot.retrieve_data +#: telebot.TeleBot.revoke_chat_invite_link telebot.TeleBot.send_animation +#: telebot.TeleBot.send_audio telebot.TeleBot.send_chat_action +#: telebot.TeleBot.send_contact telebot.TeleBot.send_dice +#: telebot.TeleBot.send_document telebot.TeleBot.send_game +#: telebot.TeleBot.send_invoice telebot.TeleBot.send_location +#: telebot.TeleBot.send_media_group telebot.TeleBot.send_message +#: telebot.TeleBot.send_photo telebot.TeleBot.send_poll +#: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue +#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo @@ -590,6 +621,7 @@ msgstr "" #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat #: telebot.TeleBot.unpin_all_chat_messages #: telebot.TeleBot.unpin_all_forum_topic_messages +#: telebot.TeleBot.unpin_all_general_forum_topic_messages #: telebot.TeleBot.unpin_chat_message telebot.TeleBot.upload_sticker_file #: telebot.TeleBot.user msgid "Return type" @@ -613,18 +645,16 @@ msgstr "" #: telebot.TeleBot.delete_sticker_set:7 telebot.TeleBot.delete_webhook:13 #: telebot.TeleBot.edit_forum_topic:23 telebot.TeleBot.leave_chat:8 #: telebot.TeleBot.log_out:11 telebot.TeleBot.pin_chat_message:19 -#: telebot.TeleBot.promote_chat_member:61 telebot.TeleBot.remove_webhook:4 +#: telebot.TeleBot.promote_chat_member:70 telebot.TeleBot.remove_webhook:4 #: telebot.TeleBot.reopen_forum_topic:14 #: telebot.TeleBot.restrict_chat_member:61 telebot.TeleBot.send_chat_action:26 -#: telebot.TeleBot.send_video_note:28 telebot.TeleBot.send_video_note:40 -#: telebot.TeleBot.send_video_note:43 #: telebot.TeleBot.set_chat_administrator_custom_title:18 #: telebot.TeleBot.set_chat_description:14 #: telebot.TeleBot.set_chat_menu_button:15 #: telebot.TeleBot.set_chat_permissions:21 telebot.TeleBot.set_chat_photo:16 #: telebot.TeleBot.set_chat_title:17 #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:11 -#: telebot.TeleBot.set_my_commands:18 +#: telebot.TeleBot.set_message_reaction:18 telebot.TeleBot.set_my_commands:18 #: telebot.TeleBot.set_my_default_administrator_rights:18 #: telebot.TeleBot.set_sticker_emoji_list:11 #: telebot.TeleBot.set_sticker_keywords:12 @@ -636,6 +666,7 @@ msgstr "" #: telebot.TeleBot.unban_chat_sender_chat:15 #: telebot.TeleBot.unpin_all_chat_messages:12 #: telebot.TeleBot.unpin_all_forum_topic_messages:14 +#: telebot.TeleBot.unpin_all_general_forum_topic_messages:12 #: telebot.TeleBot.unpin_chat_message:15 msgid ":obj:`bool`" msgstr "" @@ -873,7 +904,8 @@ msgstr "" #: of telebot.TeleBot.approve_chat_join_request:11 #: telebot.TeleBot.ban_chat_member:12 #: telebot.TeleBot.decline_chat_join_request:11 -#: telebot.TeleBot.get_chat_member:8 telebot.TeleBot.get_user_profile_photos:6 +#: telebot.TeleBot.get_chat_member:8 telebot.TeleBot.get_user_chat_boosts:8 +#: telebot.TeleBot.get_user_profile_photos:6 #: telebot.TeleBot.promote_chat_member:11 #: telebot.TeleBot.restrict_chat_member:14 #: telebot.TeleBot.set_chat_administrator_custom_title:10 @@ -886,7 +918,7 @@ msgstr "" #: telebot.TeleBot.decline_chat_join_request:14 #: telebot.TeleBot.delete_chat_photo:12 telebot.TeleBot.delete_my_commands:16 #: telebot.TeleBot.log_out:10 telebot.TeleBot.pin_chat_message:18 -#: telebot.TeleBot.promote_chat_member:60 telebot.TeleBot.remove_webhook:3 +#: telebot.TeleBot.promote_chat_member:69 telebot.TeleBot.remove_webhook:3 #: telebot.TeleBot.set_chat_administrator_custom_title:17 #: telebot.TeleBot.set_chat_description:13 #: telebot.TeleBot.set_chat_menu_button:14 telebot.TeleBot.set_chat_photo:15 @@ -935,8 +967,8 @@ msgstr "" #: of telebot.TeleBot.ban_chat_member:24 #: telebot.TeleBot.delete_chat_sticker_set:10 telebot.TeleBot.delete_message:22 -#: telebot.TeleBot.delete_sticker_set:6 telebot.TeleBot.delete_webhook:12 -#: telebot.TeleBot.send_chat_action:25 +#: telebot.TeleBot.delete_messages:14 telebot.TeleBot.delete_sticker_set:6 +#: telebot.TeleBot.delete_webhook:12 telebot.TeleBot.send_chat_action:25 #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:10 #: telebot.TeleBot.set_sticker_emoji_list:10 #: telebot.TeleBot.set_sticker_mask_position:11 @@ -962,11 +994,13 @@ msgstr "" #: of telebot.TeleBot.ban_chat_sender_chat:10 #: telebot.TeleBot.close_forum_topic:7 #: telebot.TeleBot.close_general_forum_topic:7 telebot.TeleBot.copy_message:5 -#: telebot.TeleBot.create_forum_topic:7 telebot.TeleBot.delete_forum_topic:7 -#: telebot.TeleBot.delete_message:13 telebot.TeleBot.edit_forum_topic:7 +#: telebot.TeleBot.copy_messages:3 telebot.TeleBot.create_forum_topic:7 +#: telebot.TeleBot.delete_forum_topic:7 telebot.TeleBot.delete_message:13 +#: telebot.TeleBot.delete_messages:8 telebot.TeleBot.edit_forum_topic:7 #: telebot.TeleBot.edit_general_forum_topic:7 #: telebot.TeleBot.edit_message_live_location:13 -#: telebot.TeleBot.forward_message:8 telebot.TeleBot.hide_general_forum_topic:7 +#: telebot.TeleBot.forward_message:8 telebot.TeleBot.forward_messages:3 +#: telebot.TeleBot.hide_general_forum_topic:7 #: telebot.TeleBot.pin_chat_message:7 telebot.TeleBot.reopen_forum_topic:7 #: telebot.TeleBot.reopen_general_forum_topic:7 #: telebot.TeleBot.send_animation:6 telebot.TeleBot.send_audio:9 @@ -998,17 +1032,20 @@ msgid "" msgstr "" #: of telebot.TeleBot.callback_query_handler:4 -#: telebot.TeleBot.channel_post_handler:10 +#: telebot.TeleBot.channel_post_handler:10 telebot.TeleBot.chat_boost_handler:4 #: telebot.TeleBot.chat_join_request_handler:5 #: telebot.TeleBot.chat_member_handler:6 #: telebot.TeleBot.chosen_inline_handler:5 #: telebot.TeleBot.edited_channel_post_handler:10 #: telebot.TeleBot.edited_message_handler:10 telebot.TeleBot.inline_handler:4 +#: telebot.TeleBot.message_reaction_count_handler:4 +#: telebot.TeleBot.message_reaction_handler:4 #: telebot.TeleBot.my_chat_member_handler:5 #: telebot.TeleBot.poll_answer_handler:5 telebot.TeleBot.poll_handler:4 #: telebot.TeleBot.pre_checkout_query_handler:4 #: telebot.TeleBot.register_callback_query_handler:6 #: telebot.TeleBot.register_channel_post_handler:15 +#: telebot.TeleBot.register_chat_boost_handler:6 #: telebot.TeleBot.register_chat_join_request_handler:6 #: telebot.TeleBot.register_chat_member_handler:6 #: telebot.TeleBot.register_chosen_inline_handler:6 @@ -1016,27 +1053,35 @@ msgstr "" #: telebot.TeleBot.register_edited_message_handler:15 #: telebot.TeleBot.register_inline_handler:6 #: telebot.TeleBot.register_message_handler:15 +#: telebot.TeleBot.register_message_reaction_count_handler:6 +#: telebot.TeleBot.register_message_reaction_handler:6 #: telebot.TeleBot.register_my_chat_member_handler:6 #: telebot.TeleBot.register_poll_answer_handler:6 #: telebot.TeleBot.register_poll_handler:6 #: telebot.TeleBot.register_pre_checkout_query_handler:6 +#: telebot.TeleBot.register_removed_chat_boost_handler:6 #: telebot.TeleBot.register_shipping_query_handler:6 +#: telebot.TeleBot.removed_chat_boost_handler:4 #: telebot.TeleBot.shipping_query_handler:4 msgid "Function executed as a filter" msgstr "" #: of telebot.TeleBot.callback_query_handler:7 -#: telebot.TeleBot.channel_post_handler:16 +#: telebot.TeleBot.channel_post_handler:16 telebot.TeleBot.chat_boost_handler:7 #: telebot.TeleBot.chat_join_request_handler:8 #: telebot.TeleBot.chat_member_handler:9 #: telebot.TeleBot.chosen_inline_handler:8 #: telebot.TeleBot.edited_channel_post_handler:16 #: telebot.TeleBot.edited_message_handler:19 telebot.TeleBot.inline_handler:7 -#: telebot.TeleBot.message_handler:50 telebot.TeleBot.my_chat_member_handler:8 +#: telebot.TeleBot.message_handler:50 +#: telebot.TeleBot.message_reaction_count_handler:7 +#: telebot.TeleBot.message_reaction_handler:7 +#: telebot.TeleBot.my_chat_member_handler:8 #: telebot.TeleBot.poll_answer_handler:8 telebot.TeleBot.poll_handler:7 #: telebot.TeleBot.pre_checkout_query_handler:7 #: telebot.TeleBot.register_callback_query_handler:12 #: telebot.TeleBot.register_channel_post_handler:21 +#: telebot.TeleBot.register_chat_boost_handler:11 #: telebot.TeleBot.register_chat_join_request_handler:12 #: telebot.TeleBot.register_chat_member_handler:12 #: telebot.TeleBot.register_chosen_inline_handler:12 @@ -1044,11 +1089,15 @@ msgstr "" #: telebot.TeleBot.register_edited_message_handler:24 #: telebot.TeleBot.register_inline_handler:12 #: telebot.TeleBot.register_message_handler:24 +#: telebot.TeleBot.register_message_reaction_count_handler:12 +#: telebot.TeleBot.register_message_reaction_handler:12 #: telebot.TeleBot.register_my_chat_member_handler:12 #: telebot.TeleBot.register_poll_answer_handler:12 #: telebot.TeleBot.register_poll_handler:12 #: telebot.TeleBot.register_pre_checkout_query_handler:11 +#: telebot.TeleBot.register_removed_chat_boost_handler:11 #: telebot.TeleBot.register_shipping_query_handler:12 +#: telebot.TeleBot.removed_chat_boost_handler:7 #: telebot.TeleBot.shipping_query_handler:7 msgid "Optional keyword arguments(custom filters)" msgstr "" @@ -1082,6 +1131,12 @@ msgstr "" msgid "Supported message content types. Must be a list. Defaults to ['text']." msgstr "" +#: of telebot.TeleBot.chat_boost_handler:1 +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostUpdated` object." +msgstr "" + #: of telebot.TeleBot.chat_join_request_handler:1 msgid "" "Handles a request to join the chat has been sent. The bot must have the " @@ -1163,6 +1218,10 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#closeforumtopic" msgstr "" +#: of telebot.TeleBot.close_forum_topic +msgid "aram chat_id" +msgstr "" + #: of telebot.TeleBot.close_forum_topic:10 msgid "Identifier of the topic to close" msgstr "" @@ -1180,7 +1239,7 @@ msgid "" "https://core.telegram.org/bots/api#closegeneralforumtopic" msgstr "" -#: of telebot.TeleBot.copy_message:1 +#: of telebot.TeleBot.copy_message:1 telebot.TeleBot.copy_messages:1 msgid "Use this method to copy messages of any kind." msgstr "" @@ -1188,7 +1247,8 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#copymessage" msgstr "" -#: of telebot.TeleBot.copy_message:8 telebot.TeleBot.forward_message:11 +#: of telebot.TeleBot.copy_message:8 telebot.TeleBot.copy_messages:6 +#: telebot.TeleBot.forward_message:11 telebot.TeleBot.forward_messages:6 msgid "" "Unique identifier for the chat where the original message was sent (or " "channel username in the format @channelusername)" @@ -1214,62 +1274,61 @@ msgid "" "caption, which can be specified instead of parse_mode" msgstr "" -#: of telebot.TeleBot.copy_message:22 telebot.TeleBot.send_animation:45 -#: telebot.TeleBot.send_audio:39 telebot.TeleBot.send_contact:20 -#: telebot.TeleBot.send_dice:12 telebot.TeleBot.send_document:26 +#: of telebot.TeleBot.copy_message:22 telebot.TeleBot.send_animation:48 +#: telebot.TeleBot.send_audio:36 telebot.TeleBot.send_contact:20 +#: telebot.TeleBot.send_dice:12 telebot.TeleBot.send_document:23 #: telebot.TeleBot.send_game:11 telebot.TeleBot.send_invoice:67 -#: telebot.TeleBot.send_location:25 telebot.TeleBot.send_message:24 +#: telebot.TeleBot.send_location:22 telebot.TeleBot.send_message:24 #: telebot.TeleBot.send_photo:22 telebot.TeleBot.send_poll:44 #: telebot.TeleBot.send_venue:27 telebot.TeleBot.send_video:35 -#: telebot.TeleBot.send_video_note:27 telebot.TeleBot.send_voice:31 +#: telebot.TeleBot.send_video_note:24 telebot.TeleBot.send_voice:28 msgid "" "Sends the message silently. Users will receive a notification with no " "sound." msgstr "" #: of telebot.TeleBot.copy_message:25 telebot.TeleBot.send_animation:34 -#: telebot.TeleBot.send_audio:57 telebot.TeleBot.send_contact:38 -#: telebot.TeleBot.send_document:50 telebot.TeleBot.send_invoice:95 +#: telebot.TeleBot.send_audio:57 telebot.TeleBot.send_contact:37 +#: telebot.TeleBot.send_dice:29 telebot.TeleBot.send_document:50 +#: telebot.TeleBot.send_game:26 telebot.TeleBot.send_invoice:95 #: telebot.TeleBot.send_location:43 telebot.TeleBot.send_media_group:15 -#: telebot.TeleBot.send_photo:25 telebot.TeleBot.send_poll:64 -#: telebot.TeleBot.send_sticker:30 telebot.TeleBot.send_venue:51 -#: telebot.TeleBot.send_video:38 telebot.TeleBot.send_video_note:42 -#: telebot.TeleBot.send_voice:43 +#: telebot.TeleBot.send_message:27 telebot.TeleBot.send_photo:25 +#: telebot.TeleBot.send_poll:64 telebot.TeleBot.send_sticker:30 +#: telebot.TeleBot.send_venue:50 telebot.TeleBot.send_video:38 +#: telebot.TeleBot.send_video_note:42 telebot.TeleBot.send_voice:43 msgid "Protects the contents of the sent message from forwarding and saving" msgstr "" -#: of telebot.TeleBot.copy_message:28 telebot.TeleBot.send_animation:37 -#: telebot.TeleBot.send_audio:29 telebot.TeleBot.send_contact:23 -#: telebot.TeleBot.send_dice:15 telebot.TeleBot.send_document:12 -#: telebot.TeleBot.send_game:14 telebot.TeleBot.send_invoice:70 -#: telebot.TeleBot.send_location:17 telebot.TeleBot.send_media_group:18 -#: telebot.TeleBot.send_message:30 telebot.TeleBot.send_photo:28 -#: telebot.TeleBot.send_poll:47 telebot.TeleBot.send_sticker:13 -#: telebot.TeleBot.send_venue:30 telebot.TeleBot.send_video:41 -#: telebot.TeleBot.send_video_note:19 telebot.TeleBot.send_voice:20 -msgid "If the message is a reply, ID of the original message" -msgstr "" - -#: of telebot.TeleBot.copy_message:31 telebot.TeleBot.send_animation:54 -#: telebot.TeleBot.send_audio:54 telebot.TeleBot.send_dice:26 -#: telebot.TeleBot.send_document:38 telebot.TeleBot.send_invoice:84 -#: telebot.TeleBot.send_location:40 telebot.TeleBot.send_media_group:24 -#: telebot.TeleBot.send_message:33 telebot.TeleBot.send_photo:31 -#: telebot.TeleBot.send_sticker:27 telebot.TeleBot.send_video:44 -#: telebot.TeleBot.send_video_note:39 telebot.TeleBot.send_voice:40 -msgid "" -"Pass True, if the message should be sent even if the specified replied-to" -" message is not found" -msgstr "" - -#: of telebot.TeleBot.copy_message:34 telebot.TeleBot.send_animation:40 -#: telebot.TeleBot.send_contact:26 telebot.TeleBot.send_dice:18 -#: telebot.TeleBot.send_document:18 telebot.TeleBot.send_game:17 -#: telebot.TeleBot.send_location:20 telebot.TeleBot.send_message:36 +#: of telebot.TeleBot.copy_message:28 telebot.TeleBot.copy_message:31 +#: telebot.TeleBot.edit_message_text:23 telebot.TeleBot.polling:44 +#: telebot.TeleBot.send_animation:37 telebot.TeleBot.send_animation:40 +#: telebot.TeleBot.send_animation:63 telebot.TeleBot.send_audio:39 +#: telebot.TeleBot.send_audio:42 telebot.TeleBot.send_audio:63 +#: telebot.TeleBot.send_contact:23 telebot.TeleBot.send_contact:26 +#: telebot.TeleBot.send_dice:20 telebot.TeleBot.send_dice:23 +#: telebot.TeleBot.send_document:26 telebot.TeleBot.send_document:29 +#: telebot.TeleBot.send_document:56 telebot.TeleBot.send_location:25 +#: telebot.TeleBot.send_location:28 telebot.TeleBot.send_media_group:18 +#: telebot.TeleBot.send_media_group:21 telebot.TeleBot.send_message:21 +#: telebot.TeleBot.send_message:30 telebot.TeleBot.send_message:33 +#: telebot.TeleBot.send_photo:28 telebot.TeleBot.send_photo:31 +#: telebot.TeleBot.send_sticker:21 telebot.TeleBot.send_sticker:24 +#: telebot.TeleBot.send_venue:30 telebot.TeleBot.send_venue:33 +#: telebot.TeleBot.send_video:41 telebot.TeleBot.send_video:44 +#: telebot.TeleBot.send_video:64 telebot.TeleBot.send_video_note:27 +#: telebot.TeleBot.send_video_note:30 telebot.TeleBot.send_video_note:48 +#: telebot.TeleBot.send_voice:31 telebot.TeleBot.send_voice:34 +msgid "deprecated." +msgstr "" + +#: of telebot.TeleBot.copy_message:34 telebot.TeleBot.send_animation:43 +#: telebot.TeleBot.send_contact:29 telebot.TeleBot.send_dice:15 +#: telebot.TeleBot.send_document:15 telebot.TeleBot.send_game:20 +#: telebot.TeleBot.send_location:17 telebot.TeleBot.send_message:36 #: telebot.TeleBot.send_photo:34 telebot.TeleBot.send_poll:53 -#: telebot.TeleBot.send_sticker:16 telebot.TeleBot.send_venue:33 -#: telebot.TeleBot.send_video:47 telebot.TeleBot.send_video_note:22 -#: telebot.TeleBot.send_voice:23 +#: telebot.TeleBot.send_sticker:13 telebot.TeleBot.send_venue:36 +#: telebot.TeleBot.send_video:47 telebot.TeleBot.send_video_note:19 +#: telebot.TeleBot.send_voice:20 msgid "" "Additional interface options. A JSON-serialized object for an inline " "keyboard, custom reply keyboard, instructions to remove reply keyboard or" @@ -1278,14 +1337,14 @@ msgstr "" #: of telebot.TeleBot.copy_message:39 telebot.TeleBot.delete_message:19 #: telebot.TeleBot.edit_message_live_location:23 -#: telebot.TeleBot.forward_message:20 telebot.TeleBot.send_animation:48 -#: telebot.TeleBot.send_audio:42 telebot.TeleBot.send_chat_action:19 -#: telebot.TeleBot.send_contact:31 telebot.TeleBot.send_dice:23 -#: telebot.TeleBot.send_document:29 telebot.TeleBot.send_location:28 -#: telebot.TeleBot.send_media_group:21 telebot.TeleBot.send_message:40 -#: telebot.TeleBot.send_photo:39 telebot.TeleBot.send_sticker:24 -#: telebot.TeleBot.send_venue:38 telebot.TeleBot.send_video:52 -#: telebot.TeleBot.send_video_note:30 telebot.TeleBot.send_voice:34 +#: telebot.TeleBot.forward_message:20 telebot.TeleBot.send_animation:51 +#: telebot.TeleBot.send_audio:45 telebot.TeleBot.send_chat_action:19 +#: telebot.TeleBot.send_contact:34 telebot.TeleBot.send_dice:26 +#: telebot.TeleBot.send_document:32 telebot.TeleBot.send_location:31 +#: telebot.TeleBot.send_media_group:24 telebot.TeleBot.send_message:40 +#: telebot.TeleBot.send_photo:39 telebot.TeleBot.send_sticker:27 +#: telebot.TeleBot.send_venue:41 telebot.TeleBot.send_video:52 +#: telebot.TeleBot.send_video_note:33 telebot.TeleBot.send_voice:37 #: telebot.TeleBot.stop_message_live_location:19 msgid "Timeout in seconds for the request." msgstr "" @@ -1297,26 +1356,49 @@ msgstr "" msgid "Identifier of a message thread, in which the message will be sent" msgstr "" -#: of telebot.TeleBot.copy_message:45 telebot.TeleBot.forward_message:26 -#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:66 -#: telebot.TeleBot.send_audio:66 telebot.TeleBot.send_contact:44 -#: telebot.TeleBot.send_dice:35 telebot.TeleBot.send_document:59 -#: telebot.TeleBot.send_game:32 telebot.TeleBot.send_invoice:101 -#: telebot.TeleBot.send_location:49 telebot.TeleBot.send_message:46 -#: telebot.TeleBot.send_photo:48 telebot.TeleBot.send_poll:70 -#: telebot.TeleBot.send_sticker:42 telebot.TeleBot.send_venue:57 -#: telebot.TeleBot.send_video:67 telebot.TeleBot.send_voice:49 -msgid "On success, the sent Message is returned." +#: of telebot.TeleBot.copy_message:45 telebot.TeleBot.send_dice:35 +#: telebot.TeleBot.send_photo:48 +msgid "Additional parameters for replies to messages" msgstr "" -#: of telebot.TeleBot.copy_message:46 telebot.TeleBot.forward_message:27 -#: telebot.TeleBot.reply_to:12 telebot.TeleBot.send_animation:67 -#: telebot.TeleBot.send_audio:67 telebot.TeleBot.send_contact:45 -#: telebot.TeleBot.send_dice:36 telebot.TeleBot.send_document:60 -#: telebot.TeleBot.send_location:50 telebot.TeleBot.send_message:47 -#: telebot.TeleBot.send_photo:49 telebot.TeleBot.send_sticker:43 -#: telebot.TeleBot.send_venue:58 telebot.TeleBot.send_video:68 -msgid ":class:`telebot.types.Message`" +#: of telebot.TeleBot.copy_message:48 +msgid "On success, the MessageId of the sent message is returned." +msgstr "" + +#: of telebot.TeleBot.copy_message:49 telebot.TeleBot.forward_messages:22 +msgid ":class:`telebot.types.MessageID`" +msgstr "" + +#: of telebot.TeleBot.copy_messages:9 telebot.TeleBot.forward_messages:9 +msgid "Message identifiers in the chat specified in from_chat_id" +msgstr "" + +#: of telebot.TeleBot.copy_messages:12 telebot.TeleBot.forward_message:5 +#: telebot.TeleBot.forward_messages:12 +msgid "" +"Sends the message silently. Users will receive a notification with no " +"sound" +msgstr "" + +#: of telebot.TeleBot.copy_messages:15 telebot.TeleBot.forward_messages:15 +msgid "Identifier of a message thread, in which the messages will be sent" +msgstr "" + +#: of telebot.TeleBot.copy_messages:18 telebot.TeleBot.forward_message:17 +#: telebot.TeleBot.forward_messages:18 +msgid "Protects the contents of the forwarded message from forwarding and saving" +msgstr "" + +#: of telebot.TeleBot.copy_messages:21 +msgid "Pass True to copy the messages without their captions" +msgstr "" + +#: of telebot.TeleBot.copy_messages:24 +msgid "On success, an array of MessageId of the sent messages is returned." +msgstr "" + +#: of telebot.TeleBot.copy_messages:25 +msgid ":obj:`list` of :class:`telebot.types.MessageID`" msgstr "" #: of telebot.TeleBot.create_chat_invite_link:1 @@ -1471,7 +1553,7 @@ msgid "" "increased order and must not exceed max_tip_amount." msgstr "" -#: of telebot.TeleBot.create_invoice_link:36 telebot.TeleBot.send_invoice:77 +#: of telebot.TeleBot.create_invoice_link:36 telebot.TeleBot.send_invoice:80 msgid "" "A JSON-serialized data about the invoice, which will be shared with the " "payment provider. A detailed description of required fields should be " @@ -1685,6 +1767,22 @@ msgstr "" msgid "Identifier of the message to delete" msgstr "" +#: of telebot.TeleBot.delete_messages:1 +msgid "" +"Use this method to delete multiple messages in a chat. The number of " +"messages to be deleted must not exceed 100. If the chat is a private " +"chat, the user must be an administrator of the chat for this to work and " +"must have the appropriate admin rights. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.delete_messages:6 +msgid "Telegram documentation: https://core.telegram.org/bots/api#deletemessages" +msgstr "" + +#: of telebot.TeleBot.delete_messages:11 +msgid "Identifiers of the messages to be deleted" +msgstr "" + #: of telebot.TeleBot.delete_my_commands:1 msgid "" "Use this method to delete the list of the bot's commands for the given " @@ -1909,7 +2007,7 @@ msgstr "" #: of telebot.TeleBot.edit_message_caption:26 #: telebot.TeleBot.edit_message_media:22 #: telebot.TeleBot.edit_message_reply_markup:17 -#: telebot.TeleBot.edit_message_text:29 +#: telebot.TeleBot.edit_message_text:32 msgid "" "On success, if edited message is sent by the bot, the edited Message is " "returned, otherwise True is returned." @@ -1968,7 +2066,7 @@ msgid "" msgstr "" #: of telebot.TeleBot.edit_message_live_location:29 -#: telebot.TeleBot.send_location:31 +#: telebot.TeleBot.send_location:34 msgid "The radius of uncertainty for the location, measured in meters; 0-1500" msgstr "" @@ -2035,7 +2133,7 @@ msgstr "" #: of telebot.TeleBot.edit_message_media:23 #: telebot.TeleBot.edit_message_reply_markup:18 -#: telebot.TeleBot.edit_message_text:30 telebot.TeleBot.set_game_score:27 +#: telebot.TeleBot.edit_message_text:33 telebot.TeleBot.set_game_score:27 msgid ":obj:`types.Message` or :obj:`bool`" msgstr "" @@ -2071,8 +2169,10 @@ msgid "" "specified instead of parse_mode" msgstr "" -#: of telebot.TeleBot.edit_message_text:23 telebot.TeleBot.send_message:21 -msgid "Disables link previews for links in this message" +#: of telebot.TeleBot.edit_message_text:29 +msgid "" +"A JSON-serialized object for options used to automatically generate " +"previews for links." msgstr "" #: of telebot.TeleBot.edited_channel_post_handler:1 @@ -2155,7 +2255,7 @@ msgstr "" msgid "exported invite link as String on success." msgstr "" -#: of telebot.TeleBot.forward_message:1 +#: of telebot.TeleBot.forward_message:1 telebot.TeleBot.forward_messages:1 msgid "Use this method to forward messages of any kind." msgstr "" @@ -2163,14 +2263,27 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#forwardmessage" msgstr "" -#: of telebot.TeleBot.forward_message:5 -msgid "" -"Sends the message silently. Users will receive a notification with no " -"sound" +#: of telebot.TeleBot.forward_message:26 telebot.TeleBot.forward_messages:21 +#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:69 +#: telebot.TeleBot.send_audio:69 telebot.TeleBot.send_contact:46 +#: telebot.TeleBot.send_dice:38 telebot.TeleBot.send_document:62 +#: telebot.TeleBot.send_game:35 telebot.TeleBot.send_invoice:104 +#: telebot.TeleBot.send_location:52 telebot.TeleBot.send_message:52 +#: telebot.TeleBot.send_photo:51 telebot.TeleBot.send_poll:73 +#: telebot.TeleBot.send_sticker:45 telebot.TeleBot.send_venue:59 +#: telebot.TeleBot.send_video:70 telebot.TeleBot.send_video_note:54 +#: telebot.TeleBot.send_voice:52 +msgid "On success, the sent Message is returned." msgstr "" -#: of telebot.TeleBot.forward_message:17 -msgid "Protects the contents of the forwarded message from forwarding and saving" +#: of telebot.TeleBot.forward_message:27 telebot.TeleBot.reply_to:12 +#: telebot.TeleBot.send_animation:70 telebot.TeleBot.send_audio:70 +#: telebot.TeleBot.send_contact:47 telebot.TeleBot.send_dice:39 +#: telebot.TeleBot.send_document:63 telebot.TeleBot.send_location:53 +#: telebot.TeleBot.send_message:53 telebot.TeleBot.send_photo:52 +#: telebot.TeleBot.send_sticker:46 telebot.TeleBot.send_venue:60 +#: telebot.TeleBot.send_video:71 telebot.TeleBot.send_video_note:55 +msgid ":class:`telebot.types.Message`" msgstr "" #: of telebot.TeleBot.get_chat:1 @@ -2186,6 +2299,7 @@ msgstr "" #: of telebot.TeleBot.get_chat:6 telebot.TeleBot.get_chat_administrators:7 #: telebot.TeleBot.get_chat_member_count:5 telebot.TeleBot.leave_chat:5 +#: telebot.TeleBot.set_message_reaction:5 msgid "" "Unique identifier for the target chat or username of the target " "supergroup or channel (in the format @channelusername)" @@ -2253,9 +2367,6 @@ msgid "Number of members in the chat." msgstr "" #: of telebot.TeleBot.get_chat_member_count:9 -#: telebot.TeleBot.send_video_note:14 telebot.TeleBot.send_video_note:17 -#: telebot.TeleBot.send_video_note:20 telebot.TeleBot.send_video_note:31 -#: telebot.TeleBot.send_video_note:46 msgid ":obj:`int`" msgstr "" @@ -2580,6 +2691,34 @@ msgstr "" msgid ":obj:`list` of :class:`telebot.types.Update`" msgstr "" +#: of telebot.TeleBot.get_user_chat_boosts:1 +msgid "" +"Use this method to get the list of boosts added to a chat by a user. " +"Requires administrator rights in the chat. Returns a UserChatBoosts " +"object." +msgstr "" + +#: of telebot.TeleBot.get_user_chat_boosts:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getuserchatboosts" +msgstr "" + +#: of telebot.TeleBot.get_user_chat_boosts:5 +#: telebot.TeleBot.send_chat_action:10 telebot.TeleBot.send_contact:5 +#: telebot.TeleBot.send_poll:6 telebot.TeleBot.send_venue:5 +#: telebot.TeleBot.stop_poll:5 +msgid "Unique identifier for the target chat or username of the target channel" +msgstr "" + +#: of telebot.TeleBot.get_user_chat_boosts:11 +msgid "On success, a UserChatBoosts object is returned." +msgstr "" + +#: of telebot.TeleBot.get_user_chat_boosts:12 +msgid ":class:`telebot.types.UserChatBoosts`" +msgstr "" + #: of telebot.TeleBot.get_user_profile_photos:1 msgid "" "Use this method to get a list of profile pictures for a user. Returns a " @@ -2804,6 +2943,19 @@ msgstr "" msgid "decorated function" msgstr "" +#: of telebot.TeleBot.message_reaction_count_handler:1 +msgid "" +"Handles new incoming message reaction count. As a parameter to the " +"decorator function, it passes " +":class:`telebot.types.MessageReactionCountUpdated` object." +msgstr "" + +#: of telebot.TeleBot.message_reaction_handler:1 +msgid "" +"Handles new incoming message reaction. As a parameter to the decorator " +"function, it passes :class:`telebot.types.MessageReactionUpdated` object." +msgstr "" + #: of telebot.TeleBot.middleware_handler:1 msgid "Function-based middleware handler decorator." msgstr "" @@ -2931,10 +3083,6 @@ msgid "" " period of time." msgstr "" -#: of telebot.TeleBot.polling:44 -msgid "Deprecated, use non_stop. Old typo, kept for backward compatibility." -msgstr "" - #: of telebot.TeleBot.polling:50 msgid "Path to watch for changes. Defaults to None" msgstr "" @@ -3048,12 +3196,25 @@ msgid "" "forum topics, supergroups only" msgstr "" +#: of telebot.TeleBot.promote_chat_member:60 +msgid "Pass True if the administrator can create the channel's stories" +msgstr "" + +#: of telebot.TeleBot.promote_chat_member:63 +msgid "Pass True if the administrator can edit the channel's stories" +msgstr "" + +#: of telebot.TeleBot.promote_chat_member:66 +msgid "Pass True if the administrator can delete the channel's stories" +msgstr "" + #: of telebot.TeleBot.register_callback_query_handler:1 msgid "Registers callback query handler." msgstr "" #: of telebot.TeleBot.register_callback_query_handler:3 #: telebot.TeleBot.register_channel_post_handler:3 +#: telebot.TeleBot.register_chat_boost_handler:3 #: telebot.TeleBot.register_chat_join_request_handler:3 #: telebot.TeleBot.register_chat_member_handler:3 #: telebot.TeleBot.register_chosen_inline_handler:3 @@ -3061,16 +3222,20 @@ msgstr "" #: telebot.TeleBot.register_edited_message_handler:3 #: telebot.TeleBot.register_inline_handler:3 #: telebot.TeleBot.register_message_handler:3 +#: telebot.TeleBot.register_message_reaction_count_handler:3 +#: telebot.TeleBot.register_message_reaction_handler:3 #: telebot.TeleBot.register_my_chat_member_handler:3 #: telebot.TeleBot.register_poll_answer_handler:3 #: telebot.TeleBot.register_poll_handler:3 #: telebot.TeleBot.register_pre_checkout_query_handler:3 +#: telebot.TeleBot.register_removed_chat_boost_handler:3 #: telebot.TeleBot.register_shipping_query_handler:3 msgid "function to be called" msgstr "" #: of telebot.TeleBot.register_callback_query_handler:9 #: telebot.TeleBot.register_channel_post_handler:18 +#: telebot.TeleBot.register_chat_boost_handler:9 #: telebot.TeleBot.register_chat_join_request_handler:9 #: telebot.TeleBot.register_chat_member_handler:9 #: telebot.TeleBot.register_chosen_inline_handler:9 @@ -3078,10 +3243,13 @@ msgstr "" #: telebot.TeleBot.register_edited_message_handler:21 #: telebot.TeleBot.register_inline_handler:9 #: telebot.TeleBot.register_message_handler:21 +#: telebot.TeleBot.register_message_reaction_count_handler:9 +#: telebot.TeleBot.register_message_reaction_handler:9 #: telebot.TeleBot.register_my_chat_member_handler:9 #: telebot.TeleBot.register_poll_answer_handler:9 #: telebot.TeleBot.register_poll_handler:9 #: telebot.TeleBot.register_pre_checkout_query_handler:8 +#: telebot.TeleBot.register_removed_chat_boost_handler:9 #: telebot.TeleBot.register_shipping_query_handler:9 msgid "" "True if you need to pass TeleBot instance to handler(useful for " @@ -3105,6 +3273,10 @@ msgstr "" msgid "Regular expression" msgstr "" +#: of telebot.TeleBot.register_chat_boost_handler:1 +msgid "Registers chat boost handler." +msgstr "" + #: of telebot.TeleBot.register_chat_join_request_handler:1 msgid "Registers chat join request handler." msgstr "" @@ -3184,6 +3356,14 @@ msgstr "" msgid "List of chat types" msgstr "" +#: of telebot.TeleBot.register_message_reaction_count_handler:1 +msgid "Registers message reaction count handler." +msgstr "" + +#: of telebot.TeleBot.register_message_reaction_handler:1 +msgid "Registers message reaction handler." +msgstr "" + #: of telebot.TeleBot.register_middleware_handler:1 msgid "Adds function-based middleware handler." msgstr "" @@ -3264,6 +3444,10 @@ msgstr "" msgid "Registers pre-checkout request handler." msgstr "" +#: of telebot.TeleBot.register_removed_chat_boost_handler:1 +msgid "Registers removed chat boost handler." +msgstr "" + #: of telebot.TeleBot.register_shipping_query_handler:1 msgid "Registers shipping query handler." msgstr "" @@ -3272,6 +3456,12 @@ msgstr "" msgid "Deletes webhooks using set_webhook() function." msgstr "" +#: of telebot.TeleBot.removed_chat_boost_handler:1 +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostRemoved` object." +msgstr "" + #: of telebot.TeleBot.reopen_forum_topic:1 msgid "" "Use this method to reopen a closed topic in a forum supergroup chat. The " @@ -3557,7 +3747,7 @@ msgid "Animation height" msgstr "" #: of telebot.TeleBot.send_animation:22 telebot.TeleBot.send_video:20 -#: telebot.TeleBot.send_video_note:33 +#: telebot.TeleBot.send_video_note:36 msgid "" "Thumbnail of the file sent; can be ignored if thumbnail generation for " "the file is supported server-side. The thumbnail should be in JPEG format" @@ -3578,7 +3768,7 @@ msgstr "" msgid "Mode for parsing entities in the animation caption" msgstr "" -#: of telebot.TeleBot.send_animation:51 telebot.TeleBot.send_video:29 +#: of telebot.TeleBot.send_animation:54 telebot.TeleBot.send_video:29 msgid "" "List of special entities that appear in the caption, which can be " "specified instead of parse_mode" @@ -3592,10 +3782,13 @@ msgstr "" msgid "Pass True, if the animation should be sent as a spoiler" msgstr "" -#: of telebot.TeleBot.send_animation:63 telebot.TeleBot.send_audio:63 -#: telebot.TeleBot.send_document:56 telebot.TeleBot.send_video:64 -#: telebot.TeleBot.send_video_note:48 -msgid "Deprecated. Use thumbnail instead" +#: of telebot.TeleBot.send_animation:66 telebot.TeleBot.send_audio:66 +#: telebot.TeleBot.send_contact:43 telebot.TeleBot.send_document:59 +#: telebot.TeleBot.send_location:49 telebot.TeleBot.send_media_group:30 +#: telebot.TeleBot.send_message:46 telebot.TeleBot.send_sticker:42 +#: telebot.TeleBot.send_venue:56 telebot.TeleBot.send_video_note:51 +#: telebot.TeleBot.send_voice:49 +msgid "Reply parameters." msgstr "" #: of telebot.TeleBot.send_audio:1 @@ -3640,13 +3833,13 @@ msgstr "" msgid "Track name" msgstr "" -#: of telebot.TeleBot.send_audio:36 +#: of telebot.TeleBot.send_audio:33 msgid "" "Mode for parsing entities in the audio caption. See formatting options " "for more details." msgstr "" -#: of telebot.TeleBot.send_audio:45 +#: of telebot.TeleBot.send_audio:48 msgid "" "Thumbnail of the file sent; can be ignored if thumbnail generation for " "the file is supported server-side. The thumbnail should be in JPEG format" @@ -3657,8 +3850,8 @@ msgid "" "uploaded using multipart/form-data under " msgstr "" -#: of telebot.TeleBot.send_audio:51 telebot.TeleBot.send_document:35 -#: telebot.TeleBot.send_photo:19 telebot.TeleBot.send_voice:37 +#: of telebot.TeleBot.send_audio:54 telebot.TeleBot.send_document:38 +#: telebot.TeleBot.send_photo:19 telebot.TeleBot.send_voice:40 msgid "" "A JSON-serialized list of special entities that appear in the caption, " "which can be specified instead of parse_mode" @@ -3684,12 +3877,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendchataction" msgstr "" -#: of telebot.TeleBot.send_chat_action:10 telebot.TeleBot.send_contact:5 -#: telebot.TeleBot.send_poll:6 telebot.TeleBot.send_venue:5 -#: telebot.TeleBot.stop_poll:5 -msgid "Unique identifier for the target chat or username of the target channel" -msgstr "" - #: of telebot.TeleBot.send_chat_action:13 msgid "" "Type of action to broadcast. Choose one, depending on what the user is " @@ -3732,14 +3919,7 @@ msgstr "" msgid "Additional data about the contact in the form of a vCard, 0-2048 bytes" msgstr "" -#: of telebot.TeleBot.send_contact:34 telebot.TeleBot.send_game:23 -#: telebot.TeleBot.send_venue:41 -msgid "" -"Pass True, if the message should be sent even if one of the specified " -"replied-to messages is not found." -msgstr "" - -#: of telebot.TeleBot.send_contact:41 telebot.TeleBot.send_venue:54 +#: of telebot.TeleBot.send_contact:40 telebot.TeleBot.send_venue:53 msgid "The thread identifier of a message from which the reply will be sent" msgstr "" @@ -3761,10 +3941,6 @@ msgid "" "to “🎲”" msgstr "" -#: of telebot.TeleBot.send_dice:29 -msgid "Protects the contents of the sent message from forwarding" -msgstr "" - #: of telebot.TeleBot.send_document:1 msgid "Use this method to send general files." msgstr "" @@ -3781,17 +3957,17 @@ msgid "" "using multipart/form-data" msgstr "" -#: of telebot.TeleBot.send_document:15 +#: of telebot.TeleBot.send_document:12 msgid "" "Document caption (may also be used when resending documents by file_id), " "0-1024 characters after entities parsing" msgstr "" -#: of telebot.TeleBot.send_document:23 +#: of telebot.TeleBot.send_document:20 msgid "Mode for parsing entities in the document caption" msgstr "" -#: of telebot.TeleBot.send_document:32 +#: of telebot.TeleBot.send_document:35 msgid "" "InputFile or String : Thumbnail of the file sent; can be ignored if " "thumbnail generation for the file is supported server-side. The thumbnail" @@ -3838,14 +4014,20 @@ msgid "" " up your games via @BotFather." msgstr "" -#: of telebot.TeleBot.send_game:20 -msgid "Timeout in seconds for waiting for a response from the bot." +#: of telebot.TeleBot.send_game:14 telebot.TeleBot.send_invoice:70 +#: telebot.TeleBot.send_poll:47 +msgid "deprecated. If the message is a reply, ID of the original message" msgstr "" -#: of telebot.TeleBot.send_game:26 +#: of telebot.TeleBot.send_game:17 telebot.TeleBot.send_invoice:73 +#: telebot.TeleBot.send_poll:50 msgid "" -"Pass True, if content of the message needs to be protected from being " -"viewed by the bot." +"deprecated. Pass True, if the message should be sent even if the " +"specified replied-to message is not found" +msgstr "" + +#: of telebot.TeleBot.send_game:23 +msgid "Timeout in seconds for waiting for a response from the bot." msgstr "" #: of telebot.TeleBot.send_game:29 @@ -3854,8 +4036,12 @@ msgid "" "sent." msgstr "" -#: of telebot.TeleBot.send_game:33 telebot.TeleBot.send_invoice:102 -#: telebot.TeleBot.send_poll:71 +#: of telebot.TeleBot.send_game:32 telebot.TeleBot.send_video:67 +msgid "Reply parameters" +msgstr "" + +#: of telebot.TeleBot.send_game:36 telebot.TeleBot.send_invoice:105 +#: telebot.TeleBot.send_poll:74 msgid ":obj:`types.Message`" msgstr "" @@ -3884,14 +4070,14 @@ msgid "" " they are paying for." msgstr "" -#: of telebot.TeleBot.send_invoice:73 +#: of telebot.TeleBot.send_invoice:76 msgid "" "A JSON-serialized object for an inline keyboard. If empty, one 'Pay total" " price' button will be shown. If not empty, the first button must be a " "Pay button" msgstr "" -#: of telebot.TeleBot.send_invoice:81 telebot.TeleBot.set_webhook:39 +#: of telebot.TeleBot.send_invoice:84 telebot.TeleBot.set_webhook:39 msgid "Timeout of a request, defaults to None" msgstr "" @@ -3901,6 +4087,10 @@ msgid "" "sent" msgstr "" +#: of telebot.TeleBot.send_invoice:101 +msgid "Required if the message is a reply. Additional interface options." +msgstr "" + #: of telebot.TeleBot.send_location:1 msgid "" "Use this method to send point on the map. On success, the sent Message is" @@ -3925,13 +4115,13 @@ msgid "" "Locations, should be between 60 and 86400." msgstr "" -#: of telebot.TeleBot.send_location:34 +#: of telebot.TeleBot.send_location:37 msgid "" "For live locations, a direction in which the user is moving, in degrees. " "Must be between 1 and 360 if specified." msgstr "" -#: of telebot.TeleBot.send_location:37 +#: of telebot.TeleBot.send_location:40 msgid "" "For live locations, a maximum distance for proximity alerts about " "approaching another chat member, in meters. Must be between 1 and 100000 " @@ -3966,7 +4156,7 @@ msgstr "" msgid "Identifier of a message thread, in which the media group will be sent" msgstr "" -#: of telebot.TeleBot.send_media_group:30 +#: of telebot.TeleBot.send_media_group:33 msgid "On success, an array of Messages that were sent is returned." msgstr "" @@ -3995,10 +4185,8 @@ msgid "" "specified instead of parse_mode" msgstr "" -#: of telebot.TeleBot.send_message:27 -msgid "" -"If True, the message content will be hidden for all users except for the " -"target user" +#: of telebot.TeleBot.send_message:49 +msgid "Link preview options." msgstr "" #: of telebot.TeleBot.send_photo:1 @@ -4102,10 +4290,6 @@ msgid "" " for poll preview." msgstr "" -#: of telebot.TeleBot.send_poll:50 -msgid "Pass True, if the poll allows multiple options to be voted simultaneously." -msgstr "" - #: of telebot.TeleBot.send_poll:57 msgid "Timeout in seconds for waiting for a response from the user." msgstr "" @@ -4120,6 +4304,10 @@ msgstr "" msgid "The identifier of a message thread, in which the poll will be sent" msgstr "" +#: of telebot.TeleBot.send_poll:70 +msgid "reply parameters." +msgstr "" + #: of telebot.TeleBot.send_sticker:1 msgid "" "Use this method to send static .WEBP, animated .TGS, or video .WEBM " @@ -4138,7 +4326,7 @@ msgid "" " multipart/form-data." msgstr "" -#: of telebot.TeleBot.send_sticker:21 +#: of telebot.TeleBot.send_sticker:18 msgid "to disable the notification" msgstr "" @@ -4183,11 +4371,11 @@ msgid "" "“food/icecream”.)" msgstr "" -#: of telebot.TeleBot.send_venue:45 +#: of telebot.TeleBot.send_venue:44 msgid "Google Places identifier of the venue" msgstr "" -#: of telebot.TeleBot.send_venue:48 +#: of telebot.TeleBot.send_venue:47 msgid "Google Places type of the venue." msgstr "" @@ -4249,22 +4437,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideonote" msgstr "" -#: of telebot.TeleBot.send_video_note -msgid "param chat_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type chat_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note:7 -msgid ":obj:`int` or :obj:`str`" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param data" -msgstr "" - #: of telebot.TeleBot.send_video_note:9 msgid "" "Video note to send. Pass a file_id as String to send a video note that " @@ -4273,114 +4445,14 @@ msgid "" "unsupported" msgstr "" -#: of telebot.TeleBot.send_video_note -msgid "type data" -msgstr "" - -#: of telebot.TeleBot.send_video_note:11 telebot.TeleBot.send_video_note:37 -msgid ":obj:`str` or :class:`telebot.types.InputFile`" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param duration" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type duration" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param length" -msgstr "" - #: of telebot.TeleBot.send_video_note:16 msgid "Video width and height, i.e. diameter of the video message" msgstr "" -#: of telebot.TeleBot.send_video_note -msgid "type length" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param reply_to_message_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type reply_to_message_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param reply_markup" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type reply_markup" -msgstr "" - -#: of telebot.TeleBot.send_video_note:24 -msgid "" -":class:`telebot.types.InlineKeyboardMarkup` or " -":class:`telebot.types.ReplyKeyboardMarkup` or " -":class:`telebot.types.ReplyKeyboardRemove` or " -":class:`telebot.types.ForceReply`" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param disable_notification" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type disable_notification" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param timeout" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type timeout" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param thumbnail" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type thumbnail" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param allow_sending_without_reply" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type allow_sending_without_reply" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param protect_content" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type protect_content" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param message_thread_id" -msgstr "" - #: of telebot.TeleBot.send_video_note:45 msgid "Identifier of a message thread, in which the video note will be sent" msgstr "" -#: of telebot.TeleBot.send_video_note -msgid "type message_thread_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param thumb" -msgstr "" - #: of telebot.TeleBot.send_voice:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -4411,7 +4483,7 @@ msgstr "" msgid "Duration of the voice message in seconds" msgstr "" -#: of telebot.TeleBot.send_voice:28 +#: of telebot.TeleBot.send_voice:25 msgid "" "Mode for parsing entities in the voice message caption. See formatting " "options for more details." @@ -4593,6 +4665,35 @@ msgid "" "Message, otherwise returns True." msgstr "" +#: of telebot.TeleBot.set_message_reaction:1 +msgid "" +"Use this method to set a reaction to a message in a chat. The bot must be" +" an administrator in the chat for this to work and must have the " +"appropriate admin rights. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.set_message_reaction:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmessagereaction" +msgstr "" + +#: of telebot.TeleBot.set_message_reaction:8 +msgid "Identifier of the message to set reaction to" +msgstr "" + +#: of telebot.TeleBot.set_message_reaction:11 +msgid "" +"New list of reaction types to set on the message. Currently, as non-" +"premium users, bots can set up to one reaction per message. A custom " +"emoji reaction can be used if it is either already present on the message" +" or explicitly allowed by chat administrators." +msgstr "" + +#: of telebot.TeleBot.set_message_reaction:15 +msgid "Pass True to set the reaction with a big animation" +msgstr "" + #: of telebot.TeleBot.set_my_commands:1 msgid "Use this method to change the list of the bot's commands." msgstr "" @@ -5081,6 +5182,24 @@ msgstr "" msgid "Identifier of the topic" msgstr "" +#: of telebot.TeleBot.unpin_all_general_forum_topic_messages:1 +msgid "" +"Use this method to clear the list of pinned messages in a General forum " +"topic. The bot must be an administrator in the chat for this to work and " +"must have the can_pin_messages administrator right in the supergroup. " +"Returns True on success." +msgstr "" + +#: of telebot.TeleBot.unpin_all_general_forum_topic_messages:6 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages" +msgstr "" + +#: of telebot.TeleBot.unpin_all_general_forum_topic_messages:8 +msgid "Unique identifier for the target chat or username of chat" +msgstr "" + #: of telebot.TeleBot.unpin_chat_message:1 msgid "" "Use this method to unpin specific pinned message in a supergroup chat. " @@ -5404,3 +5523,137 @@ msgstr "" #~ " exactly 512px." #~ msgstr "" +#~ msgid "If the message is a reply, ID of the original message" +#~ msgstr "" + +#~ msgid "" +#~ "Pass True, if the message should " +#~ "be sent even if the specified " +#~ "replied-to message is not found" +#~ msgstr "" + +#~ msgid "Disables link previews for links in this message" +#~ msgstr "" + +#~ msgid "Deprecated, use non_stop. Old typo, kept for backward compatibility." +#~ msgstr "" + +#~ msgid "Deprecated. Use thumbnail instead" +#~ msgstr "" + +#~ msgid "" +#~ "Pass True, if the message should " +#~ "be sent even if one of the " +#~ "specified replied-to messages is not " +#~ "found." +#~ msgstr "" + +#~ msgid "Protects the contents of the sent message from forwarding" +#~ msgstr "" + +#~ msgid "" +#~ "Pass True, if content of the " +#~ "message needs to be protected from " +#~ "being viewed by the bot." +#~ msgstr "" + +#~ msgid "" +#~ "If True, the message content will " +#~ "be hidden for all users except for" +#~ " the target user" +#~ msgstr "" + +#~ msgid "" +#~ "Pass True, if the poll allows " +#~ "multiple options to be voted " +#~ "simultaneously." +#~ msgstr "" + +#~ msgid "param chat_id" +#~ msgstr "" + +#~ msgid "type chat_id" +#~ msgstr "" + +#~ msgid ":obj:`int` or :obj:`str`" +#~ msgstr "" + +#~ msgid "param data" +#~ msgstr "" + +#~ msgid "type data" +#~ msgstr "" + +#~ msgid ":obj:`str` or :class:`telebot.types.InputFile`" +#~ msgstr "" + +#~ msgid "param duration" +#~ msgstr "" + +#~ msgid "type duration" +#~ msgstr "" + +#~ msgid "param length" +#~ msgstr "" + +#~ msgid "type length" +#~ msgstr "" + +#~ msgid "param reply_to_message_id" +#~ msgstr "" + +#~ msgid "type reply_to_message_id" +#~ msgstr "" + +#~ msgid "param reply_markup" +#~ msgstr "" + +#~ msgid "type reply_markup" +#~ msgstr "" + +#~ msgid "" +#~ ":class:`telebot.types.InlineKeyboardMarkup` or " +#~ ":class:`telebot.types.ReplyKeyboardMarkup` or " +#~ ":class:`telebot.types.ReplyKeyboardRemove` or " +#~ ":class:`telebot.types.ForceReply`" +#~ msgstr "" + +#~ msgid "param disable_notification" +#~ msgstr "" + +#~ msgid "type disable_notification" +#~ msgstr "" + +#~ msgid "param timeout" +#~ msgstr "" + +#~ msgid "type timeout" +#~ msgstr "" + +#~ msgid "param thumbnail" +#~ msgstr "" + +#~ msgid "type thumbnail" +#~ msgstr "" + +#~ msgid "param allow_sending_without_reply" +#~ msgstr "" + +#~ msgid "type allow_sending_without_reply" +#~ msgstr "" + +#~ msgid "param protect_content" +#~ msgstr "" + +#~ msgid "type protect_content" +#~ msgstr "" + +#~ msgid "param message_thread_id" +#~ msgstr "" + +#~ msgid "type message_thread_id" +#~ msgstr "" + +#~ msgid "param thumb" +#~ msgstr "" + diff --git a/docs/source/locales/en/LC_MESSAGES/types.po b/docs/source/locales/en/LC_MESSAGES/types.po index c846273fe..1dfef7706 100644 --- a/docs/source/locales/en/LC_MESSAGES/types.po +++ b/docs/source/locales/en/LC_MESSAGES/types.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-08 23:07+0500\n" +"POT-Creation-Date: 2024-01-05 22:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -25,26 +25,35 @@ msgstr "" #: of telebot.types.Animation:1 telebot.types.Audio:1 #: telebot.types.BotDescription:1 telebot.types.BotName:1 #: telebot.types.BotShortDescription:1 telebot.types.CallbackQuery:1 -#: telebot.types.Chat:1 telebot.types.ChatJoinRequest:1 +#: telebot.types.Chat:1 telebot.types.ChatBoost:1 +#: telebot.types.ChatBoostRemoved:1 telebot.types.ChatBoostSource:1 +#: telebot.types.ChatBoostUpdated:1 telebot.types.ChatJoinRequest:1 #: telebot.types.ChatMember:1 telebot.types.ChatMemberUpdated:1 #: telebot.types.ChatPhoto:1 telebot.types.ChatShared:1 #: telebot.types.ChosenInlineResult:1 telebot.types.Contact:1 -#: telebot.types.Document:1 telebot.types.File:1 telebot.types.ForumTopic:1 +#: telebot.types.Document:1 telebot.types.ExternalReplyInfo:1 +#: telebot.types.File:1 telebot.types.ForumTopic:1 #: telebot.types.ForumTopicClosed:1 telebot.types.ForumTopicCreated:1 #: telebot.types.ForumTopicEdited:1 telebot.types.ForumTopicReopened:1 #: telebot.types.Game:1 telebot.types.GameHighScore:1 #: telebot.types.GeneralForumTopicHidden:1 -#: telebot.types.GeneralForumTopicUnhidden:1 telebot.types.InlineQuery:1 -#: telebot.types.Invoice:1 telebot.types.Message:1 +#: telebot.types.GeneralForumTopicUnhidden:1 telebot.types.Giveaway:1 +#: telebot.types.GiveawayCompleted:1 telebot.types.GiveawayCreated:1 +#: telebot.types.GiveawayWinners:1 telebot.types.InaccessibleMessage:1 +#: telebot.types.InlineQuery:1 telebot.types.Invoice:1 telebot.types.Message:1 #: telebot.types.MessageAutoDeleteTimerChanged:1 telebot.types.MessageID:1 -#: telebot.types.OrderInfo:1 telebot.types.PhotoSize:1 telebot.types.Poll:1 -#: telebot.types.PollOption:1 telebot.types.PreCheckoutQuery:1 -#: telebot.types.ProximityAlertTriggered:1 telebot.types.ShippingAddress:1 +#: telebot.types.MessageOrigin:1 telebot.types.MessageReactionCountUpdated:1 +#: telebot.types.MessageReactionUpdated:1 telebot.types.OrderInfo:1 +#: telebot.types.PhotoSize:1 telebot.types.Poll:1 telebot.types.PollOption:1 +#: telebot.types.PreCheckoutQuery:1 telebot.types.ProximityAlertTriggered:1 +#: telebot.types.ReactionCount:1 telebot.types.ShippingAddress:1 #: telebot.types.ShippingQuery:1 telebot.types.Sticker:1 -#: telebot.types.StickerSet:1 telebot.types.SuccessfulPayment:1 -#: telebot.types.Update:1 telebot.types.UserProfilePhotos:1 -#: telebot.types.UserShared:1 telebot.types.Venue:1 telebot.types.Video:1 -#: telebot.types.VideoChatEnded:1 telebot.types.VideoChatParticipantsInvited:1 +#: telebot.types.StickerSet:1 telebot.types.Story:1 +#: telebot.types.SuccessfulPayment:1 telebot.types.TextQuote:1 +#: telebot.types.Update:1 telebot.types.UserChatBoosts:1 +#: telebot.types.UserProfilePhotos:1 telebot.types.UsersShared:1 +#: telebot.types.Venue:1 telebot.types.Video:1 telebot.types.VideoChatEnded:1 +#: telebot.types.VideoChatParticipantsInvited:1 #: telebot.types.VideoChatScheduled:1 telebot.types.VideoChatStarted:1 #: telebot.types.VideoNote:1 telebot.types.Voice:1 telebot.types.WebhookInfo:1 #: telebot.types.WriteAccessAllowed:1 @@ -71,19 +80,24 @@ msgstr "" #: telebot.types.BotDescription telebot.types.BotName #: telebot.types.BotShortDescription telebot.types.CallbackQuery #: telebot.types.Chat telebot.types.ChatAdministratorRights -#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest -#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator -#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft -#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner -#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated -#: telebot.types.ChatPermissions telebot.types.ChatPhoto -#: telebot.types.ChatShared telebot.types.ChosenInlineResult -#: telebot.types.Contact telebot.types.Dice telebot.types.Document -#: telebot.types.File telebot.types.ForceReply telebot.types.ForumTopic +#: telebot.types.ChatBoost telebot.types.ChatBoostRemoved +#: telebot.types.ChatBoostSource telebot.types.ChatBoostSourceGiftCode +#: telebot.types.ChatBoostSourceGiveaway telebot.types.ChatBoostSourcePremium +#: telebot.types.ChatBoostUpdated telebot.types.ChatInviteLink +#: telebot.types.ChatJoinRequest telebot.types.ChatLocation +#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned +#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember +#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted +#: telebot.types.ChatMemberUpdated telebot.types.ChatPermissions +#: telebot.types.ChatPhoto telebot.types.ChatShared +#: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice +#: telebot.types.Document telebot.types.ExternalReplyInfo telebot.types.File +#: telebot.types.ForceReply telebot.types.ForumTopic #: telebot.types.ForumTopicCreated telebot.types.ForumTopicEdited -#: telebot.types.Game telebot.types.GameHighScore -#: telebot.types.InlineKeyboardButton telebot.types.InlineKeyboardMarkup -#: telebot.types.InlineKeyboardMarkup.add +#: telebot.types.Game telebot.types.GameHighScore telebot.types.Giveaway +#: telebot.types.GiveawayCompleted telebot.types.GiveawayWinners +#: telebot.types.InaccessibleMessage telebot.types.InlineKeyboardButton +#: telebot.types.InlineKeyboardMarkup telebot.types.InlineKeyboardMarkup.add #: telebot.types.InlineKeyboardMarkup.row telebot.types.InlineQuery #: telebot.types.InlineQueryResultArticle telebot.types.InlineQueryResultAudio #: telebot.types.InlineQueryResultCachedAudio @@ -109,23 +123,32 @@ msgstr "" #: telebot.types.InputVenueMessageContent telebot.types.Invoice #: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType #: telebot.types.KeyboardButtonRequestChat -#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice -#: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition +#: telebot.types.KeyboardButtonRequestUsers telebot.types.LabeledPrice +#: telebot.types.LinkPreviewOptions telebot.types.Location +#: telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message #: telebot.types.MessageAutoDeleteTimerChanged telebot.types.MessageEntity -#: telebot.types.MessageID telebot.types.OrderInfo telebot.types.PhotoSize -#: telebot.types.Poll telebot.types.Poll.add telebot.types.PollAnswer -#: telebot.types.PollOption telebot.types.PreCheckoutQuery -#: telebot.types.ProximityAlertTriggered telebot.types.ReplyKeyboardMarkup -#: telebot.types.ReplyKeyboardMarkup.add telebot.types.ReplyKeyboardMarkup.row -#: telebot.types.ReplyKeyboardRemove telebot.types.SentWebAppMessage +#: telebot.types.MessageID telebot.types.MessageOrigin +#: telebot.types.MessageOriginChannel telebot.types.MessageOriginChat +#: telebot.types.MessageOriginHiddenUser telebot.types.MessageOriginUser +#: telebot.types.MessageReactionCountUpdated +#: telebot.types.MessageReactionUpdated telebot.types.OrderInfo +#: telebot.types.PhotoSize telebot.types.Poll telebot.types.Poll.add +#: telebot.types.PollAnswer telebot.types.PollOption +#: telebot.types.PreCheckoutQuery telebot.types.ProximityAlertTriggered +#: telebot.types.ReactionCount telebot.types.ReactionType +#: telebot.types.ReactionTypeCustomEmoji telebot.types.ReactionTypeEmoji +#: telebot.types.ReplyKeyboardMarkup telebot.types.ReplyKeyboardMarkup.add +#: telebot.types.ReplyKeyboardMarkup.row telebot.types.ReplyKeyboardRemove +#: telebot.types.ReplyParameters telebot.types.SentWebAppMessage #: telebot.types.ShippingAddress telebot.types.ShippingOption #: telebot.types.ShippingOption.add_price telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet #: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat -#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos -#: telebot.types.UserShared telebot.types.Venue telebot.types.Video +#: telebot.types.TextQuote telebot.types.Update telebot.types.User +#: telebot.types.UserChatBoosts telebot.types.UserProfilePhotos +#: telebot.types.UsersShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -194,17 +217,23 @@ msgstr "" #: telebot.types.BotDescription telebot.types.BotName #: telebot.types.BotShortDescription telebot.types.CallbackQuery #: telebot.types.Chat telebot.types.ChatAdministratorRights -#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest -#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator -#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft -#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner -#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated -#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions -#: telebot.types.ChatPhoto telebot.types.ChatShared -#: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice -#: telebot.types.Document telebot.types.File telebot.types.ForceReply +#: telebot.types.ChatBoost telebot.types.ChatBoostRemoved +#: telebot.types.ChatBoostSource telebot.types.ChatBoostSourceGiftCode +#: telebot.types.ChatBoostSourceGiveaway telebot.types.ChatBoostSourcePremium +#: telebot.types.ChatBoostUpdated telebot.types.ChatInviteLink +#: telebot.types.ChatJoinRequest telebot.types.ChatLocation +#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned +#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember +#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted +#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference +#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.ChatShared telebot.types.ChosenInlineResult +#: telebot.types.Contact telebot.types.Dice telebot.types.Document +#: telebot.types.ExternalReplyInfo telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game -#: telebot.types.GameHighScore telebot.types.InlineKeyboardButton +#: telebot.types.GameHighScore telebot.types.Giveaway +#: telebot.types.GiveawayCompleted telebot.types.GiveawayWinners +#: telebot.types.InaccessibleMessage telebot.types.InlineKeyboardButton #: telebot.types.InlineKeyboardMarkup telebot.types.InlineKeyboardMarkup.add #: telebot.types.InlineKeyboardMarkup.row telebot.types.InlineQuery #: telebot.types.InlineQueryResultArticle telebot.types.InlineQueryResultAudio @@ -231,22 +260,29 @@ msgstr "" #: telebot.types.InputVenueMessageContent telebot.types.Invoice #: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType #: telebot.types.KeyboardButtonRequestChat -#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice -#: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition +#: telebot.types.KeyboardButtonRequestUsers telebot.types.LabeledPrice +#: telebot.types.LinkPreviewOptions telebot.types.Location +#: telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message #: telebot.types.MessageAutoDeleteTimerChanged telebot.types.MessageEntity -#: telebot.types.MessageID telebot.types.OrderInfo telebot.types.PhotoSize -#: telebot.types.Poll telebot.types.PollAnswer telebot.types.PollOption -#: telebot.types.PreCheckoutQuery telebot.types.ProximityAlertTriggered -#: telebot.types.ReplyKeyboardMarkup telebot.types.ReplyKeyboardMarkup.add -#: telebot.types.ReplyKeyboardMarkup.row telebot.types.ReplyKeyboardRemove +#: telebot.types.MessageID telebot.types.MessageOrigin +#: telebot.types.MessageReactionCountUpdated +#: telebot.types.MessageReactionUpdated telebot.types.OrderInfo +#: telebot.types.PhotoSize telebot.types.Poll telebot.types.PollAnswer +#: telebot.types.PollOption telebot.types.PreCheckoutQuery +#: telebot.types.ProximityAlertTriggered telebot.types.ReactionCount +#: telebot.types.ReactionType telebot.types.ReactionTypeCustomEmoji +#: telebot.types.ReactionTypeEmoji telebot.types.ReplyKeyboardMarkup +#: telebot.types.ReplyKeyboardMarkup.add telebot.types.ReplyKeyboardMarkup.row +#: telebot.types.ReplyKeyboardRemove telebot.types.ReplyParameters #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingOption.add_price #: telebot.types.ShippingQuery telebot.types.Sticker telebot.types.StickerSet #: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat -#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos -#: telebot.types.UserShared telebot.types.Venue telebot.types.Video +#: telebot.types.TextQuote telebot.types.Update telebot.types.User +#: telebot.types.UserChatBoosts telebot.types.UserProfilePhotos +#: telebot.types.UsersShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -263,19 +299,26 @@ msgstr "" #: telebot.types.BotCommandScopeChatMember:15 #: telebot.types.BotCommandScopeDefault:8 telebot.types.BotDescription:8 #: telebot.types.BotName:8 telebot.types.BotShortDescription:8 -#: telebot.types.CallbackQuery:30 telebot.types.Chat:109 -#: telebot.types.ChatAdministratorRights:46 telebot.types.ChatInviteLink:34 -#: telebot.types.ChatJoinRequest:27 telebot.types.ChatLocation:11 -#: telebot.types.ChatMemberAdministrator:59 telebot.types.ChatMemberBanned:15 -#: telebot.types.ChatMemberLeft:11 telebot.types.ChatMemberMember:11 -#: telebot.types.ChatMemberOwner:17 telebot.types.ChatMemberRestricted:61 -#: telebot.types.ChatMemberUpdated:27 telebot.types.ChatPermissions:56 -#: telebot.types.ChatPhoto:21 telebot.types.ChatShared:15 -#: telebot.types.ChosenInlineResult:21 telebot.types.Contact:22 -#: telebot.types.Dice:11 telebot.types.Document:26 telebot.types.File:21 +#: telebot.types.CallbackQuery:29 telebot.types.Chat:137 +#: telebot.types.ChatAdministratorRights:55 telebot.types.ChatBoost:17 +#: telebot.types.ChatBoostRemoved:17 telebot.types.ChatBoostSource:8 +#: telebot.types.ChatBoostSourceGiftCode:11 +#: telebot.types.ChatBoostSourceGiveaway:17 +#: telebot.types.ChatBoostSourcePremium:11 telebot.types.ChatBoostUpdated:11 +#: telebot.types.ChatInviteLink:34 telebot.types.ChatJoinRequest:27 +#: telebot.types.ChatLocation:11 telebot.types.ChatMemberAdministrator:68 +#: telebot.types.ChatMemberBanned:15 telebot.types.ChatMemberLeft:11 +#: telebot.types.ChatMemberMember:11 telebot.types.ChatMemberOwner:17 +#: telebot.types.ChatMemberRestricted:61 telebot.types.ChatMemberUpdated:27 +#: telebot.types.ChatPermissions:55 telebot.types.ChatPhoto:21 +#: telebot.types.ChatShared:15 telebot.types.ChosenInlineResult:21 +#: telebot.types.Contact:22 telebot.types.Dice:11 telebot.types.Document:26 +#: telebot.types.ExternalReplyInfo:75 telebot.types.File:21 #: telebot.types.ForceReply:18 telebot.types.ForumTopic:17 #: telebot.types.ForumTopicCreated:14 telebot.types.Game:25 -#: telebot.types.GameHighScore:14 telebot.types.InlineKeyboardButton:49 +#: telebot.types.GameHighScore:14 telebot.types.Giveaway:29 +#: telebot.types.GiveawayCompleted:14 telebot.types.GiveawayWinners:38 +#: telebot.types.InaccessibleMessage:14 telebot.types.InlineKeyboardButton:49 #: telebot.types.InlineKeyboardMarkup:28 telebot.types.InlineQuery:26 #: telebot.types.InlineQueryResultArticle:38 #: telebot.types.InlineQueryResultAudio:40 @@ -303,28 +346,34 @@ msgstr "" #: telebot.types.InputMediaAnimation:40 telebot.types.InputMediaAudio:37 #: telebot.types.InputMediaDocument:32 telebot.types.InputMediaPhoto:24 #: telebot.types.InputMediaVideo:43 telebot.types.InputSticker:18 -#: telebot.types.InputTextMessageContent:19 +#: telebot.types.InputTextMessageContent:22 #: telebot.types.InputVenueMessageContent:30 telebot.types.Invoice:22 -#: telebot.types.KeyboardButton:33 telebot.types.KeyboardButtonPollType:9 +#: telebot.types.KeyboardButton:36 telebot.types.KeyboardButtonPollType:9 #: telebot.types.KeyboardButtonRequestChat:35 -#: telebot.types.KeyboardButtonRequestUser:18 telebot.types.LabeledPrice:13 -#: telebot.types.Location:25 telebot.types.LoginUrl:24 -#: telebot.types.MaskPosition:20 telebot.types.MenuButtonCommands:8 -#: telebot.types.MenuButtonDefault:8 telebot.types.MenuButtonWebApp:15 -#: telebot.types.Message:252 telebot.types.MessageAutoDeleteTimerChanged:8 -#: telebot.types.MessageEntity:32 telebot.types.MessageID:8 -#: telebot.types.OrderInfo:17 telebot.types.PhotoSize:21 telebot.types.Poll:47 -#: telebot.types.PollAnswer:15 telebot.types.PollOption:11 -#: telebot.types.PreCheckoutQuery:28 telebot.types.ProximityAlertTriggered:14 -#: telebot.types.ReplyKeyboardMarkup:49 telebot.types.ReplyKeyboardRemove:18 +#: telebot.types.KeyboardButtonRequestUsers:21 telebot.types.LabeledPrice:13 +#: telebot.types.LinkPreviewOptions:20 telebot.types.Location:25 +#: telebot.types.LoginUrl:24 telebot.types.MaskPosition:20 +#: telebot.types.MenuButtonCommands:8 telebot.types.MenuButtonDefault:8 +#: telebot.types.MenuButtonWebApp:15 telebot.types.Message:277 +#: telebot.types.MessageAutoDeleteTimerChanged:8 telebot.types.MessageEntity:32 +#: telebot.types.MessageID:8 telebot.types.MessageOrigin:23 +#: telebot.types.MessageReactionCountUpdated:17 +#: telebot.types.MessageReactionUpdated:26 telebot.types.OrderInfo:17 +#: telebot.types.PhotoSize:21 telebot.types.Poll:47 telebot.types.PollAnswer:18 +#: telebot.types.PollOption:11 telebot.types.PreCheckoutQuery:28 +#: telebot.types.ProximityAlertTriggered:14 telebot.types.ReactionCount:11 +#: telebot.types.ReactionType:8 telebot.types.ReactionTypeCustomEmoji:11 +#: telebot.types.ReactionTypeEmoji:11 telebot.types.ReplyKeyboardMarkup:49 +#: telebot.types.ReplyKeyboardRemove:18 telebot.types.ReplyParameters:26 #: telebot.types.SentWebAppMessage:9 telebot.types.ShippingAddress:23 #: telebot.types.ShippingOption:14 telebot.types.ShippingQuery:17 -#: telebot.types.Sticker:54 telebot.types.StickerSet:30 +#: telebot.types.Sticker:54 telebot.types.StickerSet:29 #: telebot.types.SuccessfulPayment:28 -#: telebot.types.SwitchInlineQueryChosenChat:22 telebot.types.Update:61 -#: telebot.types.User:41 telebot.types.UserProfilePhotos:11 -#: telebot.types.UserShared:15 telebot.types.Venue:27 telebot.types.Video:35 -#: telebot.types.VideoChatEnded:8 telebot.types.VideoChatParticipantsInvited:8 +#: telebot.types.SwitchInlineQueryChosenChat:22 telebot.types.TextQuote:17 +#: telebot.types.Update:75 telebot.types.User:41 telebot.types.UserChatBoosts:8 +#: telebot.types.UserProfilePhotos:11 telebot.types.UsersShared:17 +#: telebot.types.Venue:27 telebot.types.Video:35 telebot.types.VideoChatEnded:8 +#: telebot.types.VideoChatParticipantsInvited:8 #: telebot.types.VideoChatScheduled:9 telebot.types.VideoNote:24 #: telebot.types.Voice:23 telebot.types.WebAppData:12 #: telebot.types.WebAppInfo:8 telebot.types.WebhookInfo:37 @@ -342,17 +391,23 @@ msgstr "" #: telebot.types.BotDescription telebot.types.BotName #: telebot.types.BotShortDescription telebot.types.CallbackQuery #: telebot.types.Chat telebot.types.ChatAdministratorRights -#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest -#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator -#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft -#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner -#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated -#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions -#: telebot.types.ChatPhoto telebot.types.ChatShared -#: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice -#: telebot.types.Document telebot.types.File telebot.types.ForceReply +#: telebot.types.ChatBoost telebot.types.ChatBoostRemoved +#: telebot.types.ChatBoostSource telebot.types.ChatBoostSourceGiftCode +#: telebot.types.ChatBoostSourceGiveaway telebot.types.ChatBoostSourcePremium +#: telebot.types.ChatBoostUpdated telebot.types.ChatInviteLink +#: telebot.types.ChatJoinRequest telebot.types.ChatLocation +#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned +#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember +#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted +#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference +#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.ChatShared telebot.types.ChosenInlineResult +#: telebot.types.Contact telebot.types.Dice telebot.types.Document +#: telebot.types.ExternalReplyInfo telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game -#: telebot.types.GameHighScore telebot.types.InlineKeyboardButton +#: telebot.types.GameHighScore telebot.types.Giveaway +#: telebot.types.GiveawayCompleted telebot.types.GiveawayWinners +#: telebot.types.InaccessibleMessage telebot.types.InlineKeyboardButton #: telebot.types.InlineKeyboardMarkup telebot.types.InlineKeyboardMarkup.add #: telebot.types.InlineKeyboardMarkup.row telebot.types.InlineQuery #: telebot.types.InlineQueryResultArticle telebot.types.InlineQueryResultAudio @@ -379,22 +434,29 @@ msgstr "" #: telebot.types.InputVenueMessageContent telebot.types.Invoice #: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType #: telebot.types.KeyboardButtonRequestChat -#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice -#: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition +#: telebot.types.KeyboardButtonRequestUsers telebot.types.LabeledPrice +#: telebot.types.LinkPreviewOptions telebot.types.Location +#: telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message #: telebot.types.MessageAutoDeleteTimerChanged telebot.types.MessageEntity -#: telebot.types.MessageID telebot.types.OrderInfo telebot.types.PhotoSize -#: telebot.types.Poll telebot.types.PollAnswer telebot.types.PollOption -#: telebot.types.PreCheckoutQuery telebot.types.ProximityAlertTriggered -#: telebot.types.ReplyKeyboardMarkup telebot.types.ReplyKeyboardMarkup.add -#: telebot.types.ReplyKeyboardMarkup.row telebot.types.ReplyKeyboardRemove +#: telebot.types.MessageID telebot.types.MessageOrigin +#: telebot.types.MessageReactionCountUpdated +#: telebot.types.MessageReactionUpdated telebot.types.OrderInfo +#: telebot.types.PhotoSize telebot.types.Poll telebot.types.PollAnswer +#: telebot.types.PollOption telebot.types.PreCheckoutQuery +#: telebot.types.ProximityAlertTriggered telebot.types.ReactionCount +#: telebot.types.ReactionType telebot.types.ReactionTypeCustomEmoji +#: telebot.types.ReactionTypeEmoji telebot.types.ReplyKeyboardMarkup +#: telebot.types.ReplyKeyboardMarkup.add telebot.types.ReplyKeyboardMarkup.row +#: telebot.types.ReplyKeyboardRemove telebot.types.ReplyParameters #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet #: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat -#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos -#: telebot.types.UserShared telebot.types.Venue telebot.types.Video +#: telebot.types.TextQuote telebot.types.Update telebot.types.User +#: telebot.types.UserChatBoosts telebot.types.UserProfilePhotos +#: telebot.types.UsersShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -801,38 +863,37 @@ msgstr "" #: of telebot.types.CallbackQuery:11 msgid "" -"Optional. Message with the callback button that originated the query. " -"Note that message content and message date will not be available if the " -"message is too old" +"Optional. Message sent by the bot with the callback button that " +"originated the query" msgstr "" -#: of telebot.types.CallbackQuery:15 +#: of telebot.types.CallbackQuery:14 msgid "" "Optional. Identifier of the message sent via the bot in inline mode, that" " originated the query." msgstr "" -#: of telebot.types.CallbackQuery:19 +#: of telebot.types.CallbackQuery:18 msgid "" "Global identifier, uniquely corresponding to the chat to which the " "message with the callback button was sent. Useful for high scores in " "games." msgstr "" -#: of telebot.types.CallbackQuery:23 +#: of telebot.types.CallbackQuery:22 msgid "" "Optional. Data associated with the callback button. Be aware that the " "message originated the query can contain no callback buttons with this " "data." msgstr "" -#: of telebot.types.CallbackQuery:27 +#: of telebot.types.CallbackQuery:26 msgid "" "Optional. Short name of a Game to be returned, serves as the unique " "identifier for the game" msgstr "" -#: of telebot.types.CallbackQuery:31 +#: of telebot.types.CallbackQuery:30 msgid ":class:`telebot.types.CallbackQuery`" msgstr "" @@ -891,114 +952,159 @@ msgstr "" #: of telebot.types.Chat:35 msgid "" +"Optional. List of available chat reactions; for private chats, " +"supergroups and channels. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:39 +msgid "" +"Optional. Optional. Identifier of the accent color for the chat name and " +"backgrounds of the chat photo, reply header, and link preview. See accent" +" colors for more details. Returned only in getChat. Always returned in " +"getChat." +msgstr "" + +#: of telebot.types.Chat:43 +msgid "" +"Optional. Custom emoji identifier of emoji chosen by the chat for the " +"reply header and link preview background. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:47 +msgid "" +"Optional. Identifier of the accent color for the chat's profile " +"background. See profile accent colors for more details. Returned only in " +"getChat." +msgstr "" + +#: of telebot.types.Chat:51 +msgid "" +"Optional. Custom emoji identifier of the emoji chosen by the chat for its" +" profile background. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:55 +msgid "" "Optional. Custom emoji identifier of emoji status of the other party in a" " private chat. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:39 +#: of telebot.types.Chat:59 +msgid "" +"Optional. Expiration date of the emoji status of the other party in a " +"private chat, if any. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:63 msgid "" "Optional. Bio of the other party in a private chat. Returned only in " "getChat." msgstr "" -#: of telebot.types.Chat:42 +#: of telebot.types.Chat:66 msgid "" "Optional. :obj:`bool`, if privacy settings of the other party in the " "private chat allows to use tg://user?id= links only in chats " "with the user. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:46 +#: of telebot.types.Chat:70 msgid "" "Optional. True, if the privacy settings of the other party restrict " "sending voice and video note messages in the private chat. Returned only " "in getChat." msgstr "" -#: of telebot.types.Chat:48 +#: of telebot.types.Chat:72 msgid ":type :obj:`bool`" msgstr "" -#: of telebot.types.Chat:50 +#: of telebot.types.Chat:74 msgid "" "Optional. :obj:`bool`, if users need to join the supergroup before they " "can send messages. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:54 +#: of telebot.types.Chat:78 msgid "" "Optional. :obj:`bool`, if all users directly joining the supergroup need " "to be approved by supergroup administrators. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:58 +#: of telebot.types.Chat:82 msgid "" "Optional. Description, for groups, supergroups and channel chats. " "Returned only in getChat." msgstr "" -#: of telebot.types.Chat:61 +#: of telebot.types.Chat:85 msgid "" "Optional. Primary invite link, for groups, supergroups and channel chats." " Returned only in getChat." msgstr "" -#: of telebot.types.Chat:65 +#: of telebot.types.Chat:89 msgid "" "Optional. The most recent pinned message (by sending date). Returned only" " in getChat." msgstr "" -#: of telebot.types.Chat:68 +#: of telebot.types.Chat:92 msgid "" "Optional. Default chat member permissions, for groups and supergroups. " "Returned only in getChat." msgstr "" -#: of telebot.types.Chat:72 +#: of telebot.types.Chat:96 msgid "" "Optional. For supergroups, the minimum allowed delay between consecutive " "messages sent by each unpriviledged user; in seconds. Returned only in " "getChat." msgstr "" -#: of telebot.types.Chat:76 +#: of telebot.types.Chat:100 msgid "" "Optional. The time after which all messages sent to the chat will be " "automatically deleted; in seconds. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:80 +#: of telebot.types.Chat:104 msgid "" "Optional. :obj:`bool`, if the chat has enabled aggressive anti-spam " "protection. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:84 +#: of telebot.types.Chat:108 msgid "" "Optional. :obj:`bool`, if the chat has enabled hidden members. Returned " "only in getChat." msgstr "" -#: of telebot.types.Chat:88 +#: of telebot.types.Chat:112 msgid "" "Optional. :obj:`bool`, if messages from the chat can't be forwarded to " "other chats. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:92 +#: of telebot.types.Chat:116 +msgid "" +"Optional. True, if new chat members will have access to old messages; " +"available only to chat administrators. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:120 msgid "" "Optional. For supergroups, name of group sticker set. Returned only in " "getChat." msgstr "" -#: of telebot.types.Chat:95 +#: of telebot.types.Chat:123 msgid "" "Optional. :obj:`bool`, if the bot can change the group sticker set. " "Returned only in getChat." msgstr "" -#: of telebot.types.Chat:99 +#: of telebot.types.Chat:127 msgid "" "Optional. Unique identifier for the linked chat, i.e. the discussion " "group identifier for a channel and vice versa; for supergroups and " @@ -1009,13 +1115,13 @@ msgid "" "in getChat." msgstr "" -#: of telebot.types.Chat:105 +#: of telebot.types.Chat:133 msgid "" "Optional. For supergroups, the location to which the supergroup is " "connected. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:110 +#: of telebot.types.Chat:138 msgid ":class:`telebot.types.Chat`" msgstr "" @@ -1117,10 +1223,203 @@ msgid "" "reopen forum topics; supergroups only" msgstr "" -#: of telebot.types.ChatAdministratorRights:47 +#: of telebot.types.ChatAdministratorRights:46 +#: telebot.types.ChatMemberAdministrator:59 +msgid "Optional. True, if the administrator can post channel stories" +msgstr "" + +#: of telebot.types.ChatAdministratorRights:49 +#: telebot.types.ChatMemberAdministrator:62 +msgid "Optional. True, if the administrator can edit stories" +msgstr "" + +#: of telebot.types.ChatAdministratorRights:52 +#: telebot.types.ChatMemberAdministrator:65 +msgid "Optional. True, if the administrator can delete stories of other users" +msgstr "" + +#: of telebot.types.ChatAdministratorRights:56 msgid ":class:`telebot.types.ChatAdministratorRights`" msgstr "" +#: of telebot.types.ChatBoost:1 +msgid "This object contains information about a chat boost." +msgstr "" + +#: of telebot.types.ChatBoost:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#chatboost" +msgstr "" + +#: of telebot.types.ChatBoost:5 telebot.types.ChatBoostRemoved:8 +msgid "Unique identifier of the boost" +msgstr "" + +#: of telebot.types.ChatBoost:8 +msgid "Point in time (Unix timestamp) when the chat was boosted" +msgstr "" + +#: of telebot.types.ChatBoost:11 +msgid "" +"Point in time (Unix timestamp) when the boost will automatically expire, " +"unless the booster's Telegram Premium subscription is prolonged" +msgstr "" + +#: of telebot.types.ChatBoost:14 +msgid "Source of the added boost" +msgstr "" + +#: of telebot.types.ChatBoost:18 +msgid ":class:`ChatBoost`" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:1 +msgid "This object represents a boost removed from a chat." +msgstr "" + +#: of telebot.types.ChatBoostRemoved:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostremoved" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:5 telebot.types.ChatBoostUpdated:5 +msgid "Chat which was boosted" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:11 +msgid "Point in time (Unix timestamp) when the boost was removed" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:14 +msgid "Source of the removed boost" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:18 +msgid ":class:`ChatBoostRemoved`" +msgstr "" + +#: of telebot.types.ChatBoostSource:1 +msgid "This object describes the source of a chat boost." +msgstr "" + +#: of telebot.types.ChatBoostSource:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#chatboostsource" +msgstr "" + +#: of telebot.types.ChatBoostSource:5 +msgid "Source of the boost" +msgstr "" + +#: of telebot.types.ChatBoostSource:9 +msgid ":class:`ChatBoostSource`" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:1 +#: telebot.types.ChatBoostSourceGiveaway:1 +#: telebot.types.ChatBoostSourcePremium:1 +msgid "Bases: :py:class:`telebot.types.ChatBoostSource`" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:1 +msgid "" +"The boost was obtained by the creation of Telegram Premium gift codes to " +"boost a chat." +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostsourcegiftcode" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:5 +msgid "Source of the boost, always “gift_code”" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:8 +msgid "User for which the gift code was created" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:12 +msgid ":class:`ChatBoostSourceGiftCode`" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:1 +msgid "The boost was obtained by the creation of a Telegram Premium giveaway." +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostsourcegiveaway" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:5 +msgid "Source of the boost, always “giveaway”" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:8 +msgid "" +"Identifier of a message in the chat with the giveaway; the message could " +"have been deleted already. May be 0 if the message isn't sent yet." +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:11 +msgid "User that won the prize in the giveaway if any" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:14 +msgid "" +"True, if the giveaway was completed, but there was no user to win the " +"prize" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:18 +msgid ":class:`ChatBoostSourceGiveaway`" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:1 +msgid "" +"The boost was obtained by subscribing to Telegram Premium or by gifting a" +" Telegram Premium subscription to another user." +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostsourcepremium" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:5 +msgid "Source of the boost, always “premium”" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:8 +msgid "User that boosted the chat" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:12 +msgid ":class:`ChatBoostSourcePremium`" +msgstr "" + +#: of telebot.types.ChatBoostUpdated:1 +msgid "This object represents a boost added to a chat or changed." +msgstr "" + +#: of telebot.types.ChatBoostUpdated:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostupdated" +msgstr "" + +#: of telebot.types.ChatBoostUpdated:8 +msgid "Infomation about the chat boost" +msgstr "" + +#: of telebot.types.ChatBoostUpdated:12 +msgid ":class:`ChatBoostUpdated`" +msgstr "" + #: of telebot.types.ChatInviteLink:1 msgid "Represents an invite link for a chat." msgstr "" @@ -1254,7 +1553,7 @@ msgstr "" msgid ":class:`telebot.types.ChatMemberOwner`" msgstr "" -#: of telebot.types.ChatMember:5 telebot.types.ChatMemberAdministrator:60 +#: of telebot.types.ChatMember:5 telebot.types.ChatMemberAdministrator:69 msgid ":class:`telebot.types.ChatMemberAdministrator`" msgstr "" @@ -1591,13 +1890,13 @@ msgid "" " defaults to the value of can_pin_messages" msgstr "" -#: of telebot.types.ChatPermissions:52 -msgid "" -"deprecated. True, if the user is allowed to send audios, documents, " -"photos, videos, video notes and voice notes" +#: of telebot.types.ChatPermissions:52 telebot.types.Message:27 +#: telebot.types.Message:30 telebot.types.Message:37 telebot.types.Message:40 +#: telebot.types.Message:43 +msgid "deprecated." msgstr "" -#: of telebot.types.ChatPermissions:57 +#: of telebot.types.ChatPermissions:56 msgid ":class:`telebot.types.ChatPermissions`" msgstr "" @@ -1650,7 +1949,7 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#Chatshared" msgstr "" -#: of telebot.types.ChatShared:6 telebot.types.UserShared:6 +#: of telebot.types.ChatShared:6 msgid "identifier of the request" msgstr "" @@ -1806,6 +2105,124 @@ msgstr "" msgid ":class:`telebot.types.Document`" msgstr "" +#: of telebot.types.ExternalReplyInfo:1 +msgid "" +"This object contains information about a message that is being replied " +"to, which may come from another chat or forum topic." +msgstr "" + +#: of telebot.types.ExternalReplyInfo:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#externalreplyinfo" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:6 +msgid "Origin of the message replied to by the given message" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:9 +msgid "" +"Optional. Chat the original message belongs to. Available only if the " +"chat is a supergroup or a channel." +msgstr "" + +#: of telebot.types.ExternalReplyInfo:12 +msgid "" +"Optional. Unique message identifier inside the original chat. Available " +"only if the original chat is a supergroup or a channel." +msgstr "" + +#: of telebot.types.ExternalReplyInfo:15 +msgid "" +"Optional. Options used for link preview generation for the original " +"message, if it is a text message" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:18 +msgid "Optional. Message is an animation, information about the animation" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:21 telebot.types.Message:97 +msgid "Optional. Message is an audio file, information about the file" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:24 telebot.types.Message:100 +msgid "Optional. Message is a general file, information about the file" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:27 telebot.types.Message:103 +msgid "Optional. Message is a photo, available sizes of the photo" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:30 telebot.types.Message:106 +msgid "Optional. Message is a sticker, information about the sticker" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:33 telebot.types.Message:109 +msgid "Optional. Message is a forwarded story" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:36 telebot.types.Message:112 +msgid "Optional. Message is a video, information about the video" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:39 telebot.types.Message:115 +msgid "Optional. Message is a video note, information about the video message" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:42 telebot.types.Message:118 +msgid "Optional. Message is a voice message, information about the file" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:45 telebot.types.Message:128 +msgid "Optional. True, if the message media is covered by a spoiler animation" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:48 telebot.types.Message:131 +msgid "Optional. Message is a shared contact, information about the contact" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:51 telebot.types.Message:134 +msgid "Optional. Message is a dice with random value" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:54 telebot.types.Message:137 +msgid "" +"Optional. Message is a game, information about the game. More about games" +" »" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:57 +msgid "Optional. Message is a scheduled giveaway, information about the giveaway" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:60 +msgid "Optional. A giveaway with public winners was completed" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:63 telebot.types.Message:200 +msgid "" +"Optional. Message is an invoice for a payment, information about the " +"invoice. More about payments »" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:66 telebot.types.Message:147 +msgid "Optional. Message is a shared location, information about the location" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:69 telebot.types.Message:140 +msgid "Optional. Message is a native poll, information about the poll" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:72 +msgid "Optional. Message is a venue, information about the venue" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:76 +msgid ":class:`ExternalReplyInfo`" +msgstr "" + #: of telebot.types.File:1 msgid "" "This object represents a file ready to be downloaded. The file can be " @@ -2061,33 +2478,209 @@ msgid "" "https://core.telegram.org/bots/api#generalforumtopicunhidden" msgstr "" -#: of telebot.types.InlineKeyboardButton:1 telebot.types.InlineKeyboardMarkup:1 -#: telebot.types.LoginUrl:1 telebot.types.MessageEntity:1 -msgid "" -"Bases: :py:class:`telebot.types.Dictionaryable`, " -":py:class:`telebot.types.JsonSerializable`, " -":py:class:`telebot.types.JsonDeserializable`" +#: of telebot.types.Giveaway:1 +msgid "This object represents a message about a scheduled giveaway." msgstr "" -#: of telebot.types.InlineKeyboardButton:1 -msgid "" -"This object represents one button of an inline keyboard. You must use " -"exactly one of the optional fields." +#: of telebot.types.Giveaway:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#giveaway" msgstr "" -#: of telebot.types.InlineKeyboardButton:3 -#: telebot.types.SwitchInlineQueryChosenChat:4 -msgid "" -"Telegram Documentation: " -"https://core.telegram.org/bots/api#inlinekeyboardbutton" +#: of telebot.types.Giveaway:5 +msgid "The list of chats which the user must join to participate in the giveaway" msgstr "" -#: of telebot.types.InlineKeyboardButton:5 -#: telebot.types.InlineQueryResultsButton:6 -msgid "Label text on the button" +#: of telebot.types.Giveaway:8 +msgid "" +"Point in time (Unix timestamp) when winners of the giveaway will be " +"selected" msgstr "" -#: of telebot.types.InlineKeyboardButton:8 +#: of telebot.types.Giveaway:11 +msgid "" +"The number of users which are supposed to be selected as winners of the " +"giveaway" +msgstr "" + +#: of telebot.types.Giveaway:14 +msgid "" +"Optional. True, if only users who join the chats after the giveaway " +"started should be eligible to win" +msgstr "" + +#: of telebot.types.Giveaway:17 +msgid "" +"Optional. True, if the list of giveaway winners will be visible to " +"everyone" +msgstr "" + +#: of telebot.types.Giveaway:20 telebot.types.GiveawayWinners:35 +msgid "Optional. Description of additional giveaway prize" +msgstr "" + +#: of telebot.types.Giveaway:23 +msgid "" +"Optional. A list of two-letter ISO 3166-1 alpha-2 country codes " +"indicating the countries from which eligible users for the giveaway must " +"come. If empty, then all users can participate in the giveaway." +msgstr "" + +#: of telebot.types.Giveaway:26 telebot.types.GiveawayWinners:23 +msgid "" +"Optional. The number of months the Telegram Premium subscription won from" +" the giveaway will be active for" +msgstr "" + +#: of telebot.types.Giveaway:30 +msgid ":class:`Giveaway`" +msgstr "" + +#: of telebot.types.GiveawayCompleted:1 +msgid "" +"This object represents a service message about the completion of a " +"giveaway without public winners." +msgstr "" + +#: of telebot.types.GiveawayCompleted:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#giveawaycompleted" +msgstr "" + +#: of telebot.types.GiveawayCompleted:5 +msgid "Number of winners in the giveaway" +msgstr "" + +#: of telebot.types.GiveawayCompleted:8 telebot.types.GiveawayWinners:26 +msgid "Optional. Number of undistributed prizes" +msgstr "" + +#: of telebot.types.GiveawayCompleted:11 +msgid "" +"Optional. Message with the giveaway that was completed, if it wasn't " +"deleted" +msgstr "" + +#: of telebot.types.GiveawayCompleted:15 +msgid ":class:`GiveawayCompleted`" +msgstr "" + +#: of telebot.types.GiveawayCreated:1 +msgid "" +"This object represents a service message about the creation of a " +"scheduled giveaway. Currently holds no information." +msgstr "" + +#: of telebot.types.GiveawayWinners:1 +msgid "" +"This object represents a message about the completion of a giveaway with " +"public winners." +msgstr "" + +#: of telebot.types.GiveawayWinners:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#giveawaywinners" +msgstr "" + +#: of telebot.types.GiveawayWinners:5 +msgid "The chat that created the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:8 +msgid "Identifier of the messsage with the giveaway in the chat" +msgstr "" + +#: of telebot.types.GiveawayWinners:11 +msgid "Point in time (Unix timestamp) when winners of the giveaway were selected" +msgstr "" + +#: of telebot.types.GiveawayWinners:14 +msgid "Total number of winners in the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:17 +msgid "List of up to 100 winners of the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:20 +msgid "" +"Optional. The number of other chats the user had to join in order to be " +"eligible for the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:29 +msgid "" +"Optional. True, if only users who had joined the chats after the giveaway" +" started were eligible to win" +msgstr "" + +#: of telebot.types.GiveawayWinners:32 +msgid "" +"Optional. True, if the giveaway was canceled because the payment for it " +"was refunded" +msgstr "" + +#: of telebot.types.GiveawayWinners:39 +msgid ":class:`GiveawayWinners`" +msgstr "" + +#: of telebot.types.InaccessibleMessage:1 +msgid "" +"This object describes a message that was deleted or is otherwise " +"inaccessible to the bot." +msgstr "" + +#: of telebot.types.InaccessibleMessage:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#inaccessiblemessage" +msgstr "" + +#: of telebot.types.InaccessibleMessage:5 +msgid "Chat the message belonged to" +msgstr "" + +#: of telebot.types.InaccessibleMessage:8 telebot.types.MessageOriginChannel:6 +#: telebot.types.MessageReactionCountUpdated:8 +msgid "Unique message identifier inside the chat" +msgstr "" + +#: of telebot.types.InaccessibleMessage:11 +msgid "" +"Always 0. The field can be used to differentiate regular and inaccessible" +" messages." +msgstr "" + +#: of telebot.types.InaccessibleMessage:15 +msgid ":class:`InaccessibleMessage`" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:1 telebot.types.InlineKeyboardMarkup:1 +#: telebot.types.LoginUrl:1 telebot.types.MessageEntity:1 +msgid "" +"Bases: :py:class:`telebot.types.Dictionaryable`, " +":py:class:`telebot.types.JsonSerializable`, " +":py:class:`telebot.types.JsonDeserializable`" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:1 +msgid "" +"This object represents one button of an inline keyboard. You must use " +"exactly one of the optional fields." +msgstr "" + +#: of telebot.types.InlineKeyboardButton:3 +#: telebot.types.SwitchInlineQueryChosenChat:4 +msgid "" +"Telegram Documentation: " +"https://core.telegram.org/bots/api#inlinekeyboardbutton" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:5 +#: telebot.types.InlineQueryResultsButton:6 +msgid "Label text on the button" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:8 msgid "" "Optional. HTTP or tg:// URL to be opened when the button is pressed. " "Links tg://user?id= can be used to mention a user by their ID " @@ -3390,7 +3983,7 @@ msgstr "" #: telebot.types.InputVenueMessageContent:1 #: telebot.types.KeyboardButtonPollType:1 #: telebot.types.KeyboardButtonRequestChat:1 -#: telebot.types.KeyboardButtonRequestUser:1 +#: telebot.types.KeyboardButtonRequestUsers:1 msgid "Bases: :py:class:`telebot.types.Dictionaryable`" msgstr "" @@ -3842,11 +4435,16 @@ msgid "" " be specified instead of parse_mode" msgstr "" -#: of telebot.types.InputTextMessageContent:16 -msgid "Optional. Disables link previews for links in the sent message" +#: of telebot.types.InputTextMessageContent:16 telebot.types.KeyboardButton:25 +#: telebot.types.StickerSet:20 +msgid "deprecated" +msgstr "" + +#: of telebot.types.InputTextMessageContent:19 +msgid "Optional. Link preview generation options for the message" msgstr "" -#: of telebot.types.InputTextMessageContent:20 +#: of telebot.types.InputTextMessageContent:23 msgid ":class:`telebot.types.InputTextMessageContent`" msgstr "" @@ -3980,21 +4578,21 @@ msgid "" "service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:25 +#: of telebot.types.KeyboardButton:28 msgid "" "Optional. If specified, pressing the button will open a list of suitable " -"users. Tapping on any user will send their identifier to the bot in a " -"“user_shared” service message. Available in private chats only." +"users. Identifiers of selected users will be sent to the bot in a " +"“users_shared” service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:29 +#: of telebot.types.KeyboardButton:32 msgid "" "Optional. If specified, pressing the button will open a list of suitable " "chats. Tapping on a chat will send its identifier to the bot in a " "“chat_shared” service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:34 +#: of telebot.types.KeyboardButton:37 msgid ":class:`telebot.types.KeyboardButton`" msgstr "" @@ -4094,39 +4692,51 @@ msgid ":class:`telebot.types.KeyboardButtonRequestChat`" msgstr "" #: of telebot.types.KeyboardButtonRequestUser:1 +msgid "Bases: :py:class:`telebot.types.KeyboardButtonRequestUsers`" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:1 +msgid "Deprecated. Use KeyboardButtonRequestUsers instead." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUsers:1 msgid "" "This object defines the criteria used to request a suitable user. The " "identifier of the selected user will be shared with the bot when the " "corresponding button is pressed." msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:4 +#: of telebot.types.KeyboardButtonRequestUsers:4 msgid "" "Telegram documentation: " -"https://core.telegram.org/bots/api#keyboardbuttonrequestuser" +"https://core.telegram.org/bots/api#keyboardbuttonrequestusers" msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:6 +#: of telebot.types.KeyboardButtonRequestUsers:6 msgid "" "Signed 32-bit identifier of the request, which will be received back in " -"the UserShared object. Must be unique within the message" +"the UsersShared object. Must be unique within the message" msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:10 +#: of telebot.types.KeyboardButtonRequestUsers:10 msgid "" "Optional. Pass True to request a bot, pass False to request a regular " "user. If not specified, no additional restrictions are applied." msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:14 +#: of telebot.types.KeyboardButtonRequestUsers:14 msgid "" "Optional. Pass True to request a premium user, pass False to request a " "non-premium user. If not specified, no additional restrictions are " "applied." msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:19 -msgid ":class:`telebot.types.KeyboardButtonRequestUser`" +#: of telebot.types.KeyboardButtonRequestUsers:18 +msgid "Optional. The maximum number of users to be selected; 1-10. Defaults to 1." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUsers:22 +msgid ":class:`telebot.types.KeyboardButtonRequestUsers`" msgstr "" #: of telebot.types.LabeledPrice:1 @@ -4154,6 +4764,59 @@ msgstr "" msgid ":class:`telebot.types.LabeledPrice`" msgstr "" +#: of telebot.types.LinkPreviewOptions:1 telebot.types.ReactionType:1 +#: telebot.types.ReplyParameters:1 telebot.types.SwitchInlineQueryChosenChat:1 +#: telebot.types.User:1 +msgid "" +"Bases: :py:class:`telebot.types.JsonDeserializable`, " +":py:class:`telebot.types.Dictionaryable`, " +":py:class:`telebot.types.JsonSerializable`" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:1 +msgid "Describes the options used for link preview generation." +msgstr "" + +#: of telebot.types.LinkPreviewOptions:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#linkpreviewoptions" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:5 +msgid "Optional. True, if the link preview is disabled" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:8 +msgid "" +"Optional. URL to use for the link preview. If empty, then the first URL " +"found in the message text will be used" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:11 +msgid "" +"Optional. True, if the media in the link preview is supposed to be " +"shrunk; ignored if the URL isn't explicitly specified or media size " +"change isn't supported for the preview" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:14 +msgid "" +"Optional. True, if the media in the link preview is supposed to be " +"enlarged; ignored if the URL isn't explicitly specified or media size " +"change isn't supported for the preview" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:17 +msgid "" +"Optional. True, if the link preview must be shown above the message text;" +" otherwise, the link preview will be shown below the message text" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:21 +msgid ":class:`LinkPreviewOptions`" +msgstr "" + #: of telebot.types.Location:1 msgid "This object represents a point on the map." msgstr "" @@ -4421,39 +5084,8 @@ msgstr "" msgid "Conversation the message belongs to" msgstr "" -#: of telebot.types.Message:27 -msgid "Optional. For forwarded messages, sender of the original message" -msgstr "" - -#: of telebot.types.Message:30 -msgid "" -"Optional. For messages forwarded from channels or from anonymous " -"administrators, information about the original sender chat" -msgstr "" - -#: of telebot.types.Message:34 -msgid "" -"Optional. For messages forwarded from channels, identifier of the " -"original message in the channel" -msgstr "" - -#: of telebot.types.Message:38 -msgid "" -"Optional. For forwarded messages that were originally sent in channels or" -" by an anonymous chat administrator, signature of the message sender if " -"present" -msgstr "" - -#: of telebot.types.Message:42 -msgid "" -"Optional. Sender's name for messages forwarded from users who disallow " -"adding a link to their account in forwarded messages" -msgstr "" - -#: of telebot.types.Message:46 -msgid "" -"Optional. For forwarded messages, date the original message was sent in " -"Unix time" +#: of telebot.types.Message:33 +msgid "deprecated. message in the channel" msgstr "" #: of telebot.types.Message:49 @@ -4474,148 +5106,112 @@ msgid "" msgstr "" #: of telebot.types.Message:60 -msgid "Optional. Bot through which the message was sent" +msgid "" +"Optional. Information about the message that is being replied to, which " +"may come from another chat or forum topic" msgstr "" #: of telebot.types.Message:63 -msgid "Optional. Date the message was last edited in Unix time" +msgid "" +"Optional. For replies that quote part of the original message, the quoted" +" part of the message" msgstr "" #: of telebot.types.Message:66 -msgid "Optional. :obj:`bool`, if the message can't be forwarded" +msgid "Optional. Bot through which the message was sent" msgstr "" #: of telebot.types.Message:69 +msgid "Optional. Date the message was last edited in Unix time" +msgstr "" + +#: of telebot.types.Message:72 +msgid "Optional. :obj:`bool`, if the message can't be forwarded" +msgstr "" + +#: of telebot.types.Message:75 msgid "" "Optional. The unique identifier of a media message group this message " "belongs to" msgstr "" -#: of telebot.types.Message:72 +#: of telebot.types.Message:78 msgid "" "Optional. Signature of the post author for messages in channels, or the " "custom title of an anonymous group administrator" msgstr "" -#: of telebot.types.Message:76 +#: of telebot.types.Message:82 msgid "Optional. For text messages, the actual UTF-8 text of the message" msgstr "" -#: of telebot.types.Message:79 +#: of telebot.types.Message:85 msgid "" "Optional. For text messages, special entities like usernames, URLs, bot " "commands, etc. that appear in the text" msgstr "" -#: of telebot.types.Message:83 +#: of telebot.types.Message:89 msgid "" -"Optional. Message is an animation, information about the animation. For " -"backward compatibility, when this field is set, the document field will " -"also be set" -msgstr "" - -#: of telebot.types.Message:87 -msgid "Optional. Message is an audio file, information about the file" -msgstr "" - -#: of telebot.types.Message:90 -msgid "Optional. Message is a general file, information about the file" +"Optional. Options used for link preview generation for the message, if it" +" is a text message and link preview options were changed" msgstr "" #: of telebot.types.Message:93 -msgid "Optional. Message is a photo, available sizes of the photo" -msgstr "" - -#: of telebot.types.Message:96 -msgid "Optional. Message is a sticker, information about the sticker" -msgstr "" - -#: of telebot.types.Message:99 -msgid "Optional. Message is a video, information about the video" -msgstr "" - -#: of telebot.types.Message:102 -msgid "Optional. Message is a video note, information about the video message" -msgstr "" - -#: of telebot.types.Message:105 -msgid "Optional. Message is a voice message, information about the file" +msgid "" +"Optional. Message is an animation, information about the animation. For " +"backward compatibility, when this field is set, the document field will " +"also be set" msgstr "" -#: of telebot.types.Message:108 +#: of telebot.types.Message:121 msgid "" "Optional. Caption for the animation, audio, document, photo, video or " "voice" msgstr "" -#: of telebot.types.Message:111 +#: of telebot.types.Message:124 msgid "" "Optional. For messages with a caption, special entities like usernames, " "URLs, bot commands, etc. that appear in the caption" msgstr "" -#: of telebot.types.Message:115 -msgid "Optional. True, if the message media is covered by a spoiler animation" -msgstr "" - -#: of telebot.types.Message:118 -msgid "Optional. Message is a shared contact, information about the contact" -msgstr "" - -#: of telebot.types.Message:121 -msgid "Optional. Message is a dice with random value" -msgstr "" - -#: of telebot.types.Message:124 -msgid "" -"Optional. Message is a game, information about the game. More about games" -" »" -msgstr "" - -#: of telebot.types.Message:127 -msgid "Optional. Message is a native poll, information about the poll" -msgstr "" - -#: of telebot.types.Message:130 +#: of telebot.types.Message:143 msgid "" "Optional. Message is a venue, information about the venue. For backward " "compatibility, when this field is set, the location field will also be " "set" msgstr "" -#: of telebot.types.Message:134 -msgid "Optional. Message is a shared location, information about the location" -msgstr "" - -#: of telebot.types.Message:137 +#: of telebot.types.Message:150 msgid "" "Optional. New members that were added to the group or supergroup and " "information about them (the bot itself may be one of these members)" msgstr "" -#: of telebot.types.Message:141 +#: of telebot.types.Message:154 msgid "" "Optional. A member was removed from the group, information about them " "(this member may be the bot itself)" msgstr "" -#: of telebot.types.Message:145 +#: of telebot.types.Message:158 msgid "Optional. A chat title was changed to this value" msgstr "" -#: of telebot.types.Message:148 +#: of telebot.types.Message:161 msgid "Optional. A chat photo was change to this value" msgstr "" -#: of telebot.types.Message:151 +#: of telebot.types.Message:164 msgid "Optional. Service message: the chat photo was deleted" msgstr "" -#: of telebot.types.Message:154 +#: of telebot.types.Message:167 msgid "Optional. Service message: the group has been created" msgstr "" -#: of telebot.types.Message:157 +#: of telebot.types.Message:170 msgid "" "Optional. Service message: the supergroup has been created. This field " "can't be received in a message coming through updates, because bot can't " @@ -4624,7 +5220,7 @@ msgid "" " created supergroup." msgstr "" -#: of telebot.types.Message:162 +#: of telebot.types.Message:175 msgid "" "Optional. Service message: the channel has been created. This field can't" " be received in a message coming through updates, because bot can't be a " @@ -4632,11 +5228,11 @@ msgid "" "reply_to_message if someone replies to a very first message in a channel." msgstr "" -#: of telebot.types.Message:167 +#: of telebot.types.Message:180 msgid "Optional. Service message: auto-delete timer settings changed in the chat" msgstr "" -#: of telebot.types.Message:171 +#: of telebot.types.Message:184 msgid "" "Optional. The group has been migrated to a supergroup with the specified " "identifier. This number may have more than 32 significant bits and some " @@ -4645,7 +5241,7 @@ msgid "" " double-precision float type are safe for storing this identifier." msgstr "" -#: of telebot.types.Message:177 +#: of telebot.types.Message:190 msgid "" "Optional. The supergroup has been migrated from a group with the " "specified identifier. This number may have more than 32 significant bits " @@ -4655,106 +5251,124 @@ msgid "" "identifier." msgstr "" -#: of telebot.types.Message:183 +#: of telebot.types.Message:196 msgid "" "Optional. Specified message was pinned. Note that the Message object in " "this field will not contain further reply_to_message fields even if it is" " itself a reply." msgstr "" -#: of telebot.types.Message:187 -msgid "" -"Optional. Message is an invoice for a payment, information about the " -"invoice. More about payments »" -msgstr "" - -#: of telebot.types.Message:190 +#: of telebot.types.Message:203 msgid "" "Optional. Message is a service message about a successful payment, " "information about the payment. More about payments »" msgstr "" -#: of telebot.types.Message:194 +#: of telebot.types.Message:207 msgid "Optional. Service message: a user was shared with the bot" msgstr "" -#: of telebot.types.Message:197 +#: of telebot.types.Message:210 msgid "Optional. Service message: a chat was shared with the bot" msgstr "" -#: of telebot.types.Message:200 +#: of telebot.types.Message:213 msgid "" "Optional. The domain name of the website on which the user has logged in." " More about Telegram Login »" msgstr "" -#: of telebot.types.Message:204 +#: of telebot.types.Message:217 msgid "" "Optional. Service message: the user allowed the bot added to the " "attachment menu to write messages" msgstr "" -#: of telebot.types.Message:208 +#: of telebot.types.Message:221 msgid "Optional. Telegram Passport data" msgstr "" -#: of telebot.types.Message:211 +#: of telebot.types.Message:224 msgid "" "Optional. Service message. A user in the chat triggered another user's " "proximity alert while sharing Live Location." msgstr "" -#: of telebot.types.Message:215 +#: of telebot.types.Message:228 msgid "Optional. Service message: forum topic created" msgstr "" -#: of telebot.types.Message:218 +#: of telebot.types.Message:231 msgid "Optional. Service message: forum topic edited" msgstr "" -#: of telebot.types.Message:221 +#: of telebot.types.Message:234 msgid "Optional. Service message: forum topic closed" msgstr "" -#: of telebot.types.Message:224 +#: of telebot.types.Message:237 msgid "Optional. Service message: forum topic reopened" msgstr "" -#: of telebot.types.Message:227 +#: of telebot.types.Message:240 msgid "Optional. Service message: the 'General' forum topic hidden" msgstr "" -#: of telebot.types.Message:230 +#: of telebot.types.Message:243 msgid "Optional. Service message: the 'General' forum topic unhidden" msgstr "" -#: of telebot.types.Message:233 +#: of telebot.types.Message:246 +msgid "Optional. Service message: a giveaway has been created" +msgstr "" + +#: of telebot.types.Message:249 +msgid "Optional. The message is a scheduled giveaway message" +msgstr "" + +#: of telebot.types.Message:252 +msgid "Optional. Service message: giveaway winners(public winners)" +msgstr "" + +#: of telebot.types.Message:255 +msgid "Optional. Service message: giveaway completed, without public winners" +msgstr "" + +#: of telebot.types.Message:258 msgid "Optional. Service message: video chat scheduled" msgstr "" -#: of telebot.types.Message:236 +#: of telebot.types.Message:261 msgid "Optional. Service message: video chat started" msgstr "" -#: of telebot.types.Message:239 +#: of telebot.types.Message:264 msgid "Optional. Service message: video chat ended" msgstr "" -#: of telebot.types.Message:242 +#: of telebot.types.Message:267 msgid "Optional. Service message: new participants invited to a video chat" msgstr "" -#: of telebot.types.Message:245 +#: of telebot.types.Message:270 msgid "Optional. Service message: data sent by a Web App" msgstr "" -#: of telebot.types.Message:248 +#: of telebot.types.Message:273 msgid "" "Optional. Inline keyboard attached to the message. login_url buttons are " "represented as ordinary url buttons." msgstr "" -#: of telebot.types.Message:253 +#: of telebot.types.Message +msgid "forward_origin" +msgstr "" + +#: of telebot.types.Message:46 +msgid "Optional. For forwarded messages, information about the original message;" +msgstr "" + +#: of telebot.types.Message:278 msgid ":class:`telebot.types.Message`" msgstr "" @@ -4873,12 +5487,163 @@ msgstr "" msgid ":class:`telebot.types.MessageId`" msgstr "" -#: of telebot.types.OrderInfo:1 -msgid "This object represents information about an order." +#: of telebot.types.MessageOrigin:1 +msgid "This object describes the origin of a message." msgstr "" -#: of telebot.types.OrderInfo:3 -msgid "Telegram Documentation: https://core.telegram.org/bots/api#orderinfo" +#: of telebot.types.MessageOrigin:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#messageorigin" +msgstr "" + +#: of telebot.types.MessageOrigin:5 +msgid "Type of the message origin" +msgstr "" + +#: of telebot.types.MessageOrigin:8 +msgid "Date the message was sent originally in Unix time" +msgstr "" + +#: of telebot.types.MessageOrigin:11 +msgid "User that sent the message originally (for MessageOriginUser)" +msgstr "" + +#: of telebot.types.MessageOrigin:14 +msgid "" +"Name of the user that sent the message originally (for " +"MessageOriginHiddenUser)" +msgstr "" + +#: of telebot.types.MessageOrigin:17 +msgid "Chat that sent the message originally (for MessageOriginChat)" +msgstr "" + +#: of telebot.types.MessageOrigin:20 +msgid "Optional. Author signature for certain cases" +msgstr "" + +#: of telebot.types.MessageOrigin:24 +msgid ":class:`MessageOrigin`" +msgstr "" + +#: of telebot.types.MessageOriginChannel:1 telebot.types.MessageOriginChat:1 +#: telebot.types.MessageOriginHiddenUser:1 telebot.types.MessageOriginUser:1 +msgid "Bases: :py:class:`telebot.types.MessageOrigin`" +msgstr "" + +#: of telebot.types.MessageOriginChannel:1 +msgid "The message was originally sent to a channel chat." +msgstr "" + +#: of telebot.types.MessageOriginChannel:3 +msgid "Channel chat to which the message was originally sent" +msgstr "" + +#: of telebot.types.MessageOriginChannel:9 +msgid "Optional. Signature of the original post author" +msgstr "" + +#: of telebot.types.MessageOriginChat:1 +msgid "The message was originally sent on behalf of a chat to a group chat." +msgstr "" + +#: of telebot.types.MessageOriginChat:3 +msgid "Chat that sent the message originally" +msgstr "" + +#: of telebot.types.MessageOriginChat:6 +msgid "" +"Optional. For messages originally sent by an anonymous chat " +"administrator, original message author signature" +msgstr "" + +#: of telebot.types.MessageOriginHiddenUser:1 +msgid "The message was originally sent by an unknown user." +msgstr "" + +#: of telebot.types.MessageOriginHiddenUser:3 +msgid "Name of the user that sent the message originally" +msgstr "" + +#: of telebot.types.MessageOriginUser:1 +msgid "The message was originally sent by a known user." +msgstr "" + +#: of telebot.types.MessageOriginUser:3 +msgid "User that sent the message originally" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:1 +#: telebot.types.MessageReactionUpdated:1 +msgid "" +"This object represents a service message about a change in the list of " +"the current user's reactions to a message." +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#messagereactioncountupdated" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:5 +msgid "The chat containing the message" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:11 +#: telebot.types.MessageReactionUpdated:17 +msgid "Date of the change in Unix time" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:14 +msgid "List of reactions that are present on the message" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:18 +msgid ":class:`MessageReactionCountUpdated`" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#messagereactionupdated" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:5 +msgid "The chat containing the message the user reacted to" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:8 +msgid "Unique identifier of the message inside the chat" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:11 +msgid "Optional. The user that changed the reaction, if the user isn't anonymous" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:14 +msgid "" +"Optional. The chat on behalf of which the reaction was changed, if the " +"user is anonymous" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:20 +msgid "Previous list of reaction types that were set by the user" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:23 +msgid "New list of reaction types that have been set by the user" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:27 +msgid ":class:`MessageReactionUpdated`" +msgstr "" + +#: of telebot.types.OrderInfo:1 +msgid "This object represents information about an order." +msgstr "" + +#: of telebot.types.OrderInfo:3 +msgid "Telegram Documentation: https://core.telegram.org/bots/api#orderinfo" msgstr "" #: of telebot.types.OrderInfo:5 @@ -5016,16 +5781,22 @@ msgid "Telegram Documentation: https://core.telegram.org/bots/api#pollanswer" msgstr "" #: of telebot.types.PollAnswer:8 -msgid "The user, who changed the answer to the poll" +msgid "" +"Optional. The chat that changed the answer to the poll, if the voter is " +"anonymous" msgstr "" #: of telebot.types.PollAnswer:11 +msgid "Optional. The user, who changed the answer to the poll" +msgstr "" + +#: of telebot.types.PollAnswer:14 msgid "" "0-based identifiers of answer options, chosen by the user. May be empty " "if the user retracted their vote." msgstr "" -#: of telebot.types.PollAnswer:16 +#: of telebot.types.PollAnswer:19 msgid ":class:`telebot.types.PollAnswer`" msgstr "" @@ -5112,6 +5883,88 @@ msgstr "" msgid ":class:`telebot.types.ProximityAlertTriggered`" msgstr "" +#: of telebot.types.ReactionCount:1 +msgid "" +"This object represents a reaction added to a message along with the " +"number of times it was added." +msgstr "" + +#: of telebot.types.ReactionCount:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#reactioncount" +msgstr "" + +#: of telebot.types.ReactionCount:5 telebot.types.ReactionType:5 +msgid "Type of the reaction" +msgstr "" + +#: of telebot.types.ReactionCount:8 +msgid "Number of times the reaction was added" +msgstr "" + +#: of telebot.types.ReactionCount:12 +msgid ":class:`ReactionCount`" +msgstr "" + +#: of telebot.types.ReactionType:1 +msgid "This object represents a reaction type." +msgstr "" + +#: of telebot.types.ReactionType:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#reactiontype" +msgstr "" + +#: of telebot.types.ReactionType:9 +msgid ":class:`ReactionType`" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:1 telebot.types.ReactionTypeEmoji:1 +msgid "Bases: :py:class:`telebot.types.ReactionType`" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:1 +msgid "This object represents a custom emoji reaction type." +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#reactiontypecustomemoji" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:5 +msgid "Type of the reaction, must be custom_emoji" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:8 +msgid "Identifier of the custom emoji" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:12 +msgid ":class:`ReactionTypeCustomEmoji`" +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:1 +msgid "This object represents an emoji reaction type." +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#reactiontypeemoji" +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:5 +msgid "Type of the reaction, must be emoji" +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:8 +msgid "Reaction emoji. List is available on the API doc." +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:12 +msgid ":class:`ReactionTypeEmoji`" +msgstr "" + #: of telebot.types.ReplyKeyboardMarkup:1 msgid "" "This object represents a custom keyboard with reply options (see " @@ -5265,6 +6118,65 @@ msgstr "" msgid ":class:`telebot.types.ReplyKeyboardRemove`" msgstr "" +#: of telebot.types.ReplyParameters:1 +msgid "Describes reply parameters for the message that is being sent." +msgstr "" + +#: of telebot.types.ReplyParameters:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#replyparameters" +msgstr "" + +#: of telebot.types.ReplyParameters:5 +msgid "" +"Identifier of the message that will be replied to in the current chat, or" +" in the chat chat_id if it is specified" +msgstr "" + +#: of telebot.types.ReplyParameters:8 +msgid "" +"Optional. If the message to be replied to is from a different chat, " +"unique identifier for the chat or username of the channel (in the format " +"@channelusername)" +msgstr "" + +#: of telebot.types.ReplyParameters:11 +msgid "" +"Optional. Pass True if the message should be sent even if the specified " +"message to be replied to is not found; can be used only for replies in " +"the same chat and forum topic." +msgstr "" + +#: of telebot.types.ReplyParameters:14 +msgid "" +"Optional. Quoted part of the message to be replied to; 0-1024 characters " +"after entities parsing. The quote must be an exact substring of the " +"message to be replied to, including bold, italic, underline, " +"strikethrough, spoiler, and custom_emoji entities. The message will fail " +"to send if the quote isn't found in the original message." +msgstr "" + +#: of telebot.types.ReplyParameters:17 +msgid "" +"Optional. Mode for parsing entities in the quote. See formatting options " +"for more details." +msgstr "" + +#: of telebot.types.ReplyParameters:20 +msgid "" +"Optional. A JSON-serialized list of special entities that appear in the " +"quote. It can be specified instead of quote_parse_mode." +msgstr "" + +#: of telebot.types.ReplyParameters:23 +msgid "" +"Optional. Position of the quote in the original message in UTF-16 code " +"units" +msgstr "" + +#: of telebot.types.ReplyParameters:27 +msgid ":class:`ReplyParameters`" +msgstr "" + #: of telebot.types.SentWebAppMessage:1 telebot.types.WebAppData:1 #: telebot.types.WebAppInfo:1 msgid "" @@ -5476,21 +6388,15 @@ msgstr "" msgid "True, if the sticker set contains video stickers" msgstr "" -#: of telebot.types.StickerSet:20 -msgid "" -"True, if the sticker set contains masks. Deprecated since Bot API 6.2, " -"use sticker_type instead." -msgstr "" - -#: of telebot.types.StickerSet:24 +#: of telebot.types.StickerSet:23 msgid "List of all set stickers" msgstr "" -#: of telebot.types.StickerSet:27 +#: of telebot.types.StickerSet:26 msgid "Optional. Sticker set thumbnail in the .WEBP, .TGS, or .WEBM format" msgstr "" -#: of telebot.types.StickerSet:31 +#: of telebot.types.StickerSet:30 msgid ":class:`telebot.types.StickerSet`" msgstr "" @@ -5498,6 +6404,12 @@ msgstr "" msgid "Deprecated since Bot API 6.2, use sticker_type instead." msgstr "" +#: of telebot.types.Story:1 +msgid "" +"This object represents a message about a forwarded story in the chat. " +"Currently holds no information." +msgstr "" + #: of telebot.types.SuccessfulPayment:1 msgid "This object contains basic information about a successful payment." msgstr "" @@ -5520,13 +6432,6 @@ msgstr "" msgid ":class:`telebot.types.SuccessfulPayment`" msgstr "" -#: of telebot.types.SwitchInlineQueryChosenChat:1 telebot.types.User:1 -msgid "" -"Bases: :py:class:`telebot.types.JsonDeserializable`, " -":py:class:`telebot.types.Dictionaryable`, " -":py:class:`telebot.types.JsonSerializable`" -msgstr "" - #: of telebot.types.SwitchInlineQueryChosenChat:1 msgid "" "Represents an inline button that switches the current user to inline mode" @@ -5559,6 +6464,45 @@ msgstr "" msgid ":class:`SwitchInlineQueryChosenChat`" msgstr "" +#: of telebot.types.TextQuote:1 +msgid "" +"This object contains information about the quoted part of a message that " +"is replied to by the given message." +msgstr "" + +#: of telebot.types.TextQuote:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#textquote" +msgstr "" + +#: of telebot.types.TextQuote:5 +msgid "" +"Text of the quoted part of a message that is replied to by the given " +"message" +msgstr "" + +#: of telebot.types.TextQuote:8 +msgid "" +"Optional. Special entities that appear in the quote. Currently, only " +"bold, italic, underline, strikethrough, spoiler, and custom_emoji " +"entities are kept in quotes." +msgstr "" + +#: of telebot.types.TextQuote:11 +msgid "" +"Approximate quote position in the original message in UTF-16 code units " +"as specified by the sender" +msgstr "" + +#: of telebot.types.TextQuote:14 +msgid "" +"Optional. True, if the quote was chosen manually by the message sender. " +"Otherwise, the quote was added automatically by the server." +msgstr "" + +#: of telebot.types.TextQuote:18 +msgid ":class:`TextQuote`" +msgstr "" + #: of telebot.types.Update:1 msgid "" "This object represents an incoming update.At most one of the optional " @@ -5600,66 +6544,94 @@ msgid "" msgstr "" #: of telebot.types.Update:23 +msgid "" +"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." +msgstr "" + +#: of telebot.types.Update:27 +msgid "" +"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." +msgstr "" + +#: of telebot.types.Update:31 msgid "Optional. New incoming inline query" msgstr "" -#: of telebot.types.Update:26 +#: of telebot.types.Update:34 msgid "" "Optional. The result of an inline query that was chosen by a user and " "sent to their chat partner. Please see our documentation on the feedback " "collecting for details on how to enable these updates for your bot." msgstr "" -#: of telebot.types.Update:31 +#: of telebot.types.Update:39 msgid "Optional. New incoming callback query" msgstr "" -#: of telebot.types.Update:34 +#: of telebot.types.Update:42 msgid "" "Optional. New incoming shipping query. Only for invoices with flexible " "price" msgstr "" -#: of telebot.types.Update:37 +#: of telebot.types.Update:45 msgid "" "Optional. New incoming pre-checkout query. Contains full information " "about checkout" msgstr "" -#: of telebot.types.Update:41 +#: of telebot.types.Update:49 msgid "" "Optional. New poll state. Bots receive only updates about stopped polls " "and polls, which are sent by the bot" msgstr "" -#: of telebot.types.Update:45 +#: of telebot.types.Update:53 msgid "" "Optional. A user changed their answer in a non-anonymous poll. Bots " "receive new votes only in polls that were sent by the bot itself." msgstr "" -#: of telebot.types.Update:49 +#: of telebot.types.Update:57 msgid "" "Optional. The bot's chat member status was updated in a chat. For private" " chats, this update is received only when the bot is blocked or unblocked" " by the user." msgstr "" -#: of telebot.types.Update:53 +#: of telebot.types.Update:61 msgid "" "Optional. A chat member's status was updated in a chat. The bot must be " "an administrator in the chat and must explicitly specify “chat_member” in" " the list of allowed_updates to receive these updates." msgstr "" -#: of telebot.types.Update:57 +#: of telebot.types.Update:65 msgid "" "Optional. A request to join the chat has been sent. The bot must have the" " can_invite_users administrator right in the chat to receive these " "updates." msgstr "" -#: of telebot.types.Update:62 +#: of telebot.types.Update:69 +msgid "" +"Optional. A chat boost was added or changed. The bot must be an " +"administrator in the chat to receive these updates." +msgstr "" + +#: of telebot.types.Update:72 +msgid "" +"Optional. A chat boost was removed. The bot must be an administrator in " +"the chat to receive these updates." +msgstr "" + +#: of telebot.types.Update:76 msgid ":class:`telebot.types.Update`" msgstr "" @@ -5742,6 +6714,22 @@ msgstr "" msgid "return" msgstr "" +#: of telebot.types.UserChatBoosts:1 +msgid "This object represents a list of boosts added to a chat by a user." +msgstr "" + +#: of telebot.types.UserChatBoosts:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#userchatboosts" +msgstr "" + +#: of telebot.types.UserChatBoosts:5 +msgid "The list of boosts added to the chat by the user" +msgstr "" + +#: of telebot.types.UserChatBoosts:9 +msgid ":class:`UserChatBoosts`" +msgstr "" + #: of telebot.types.UserProfilePhotos:1 msgid "This object represent a user's profile pictures." msgstr "" @@ -5764,30 +6752,33 @@ msgstr "" msgid ":class:`telebot.types.UserProfilePhotos`" msgstr "" -#: of telebot.types.UserShared:1 +#: of telebot.types.UsersShared:1 msgid "" -"This object contains information about the user whose identifier was " -"shared with the bot using a `telebot.types.KeyboardButtonRequestUser` " -"button." +"This object contains information about the users whose identifiers were " +"shared with the bot using a KeyboardButtonRequestUsers button." msgstr "" -#: of telebot.types.UserShared:4 -msgid "Telegram documentation: https://core.telegram.org/bots/api#usershared" +#: of telebot.types.UsersShared:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#usersshared" msgstr "" -#: of telebot.types.UserShared:9 +#: of telebot.types.UsersShared:6 +msgid "Identifier of the request" +msgstr "" + +#: of telebot.types.UsersShared:9 msgid "" -"Identifier of the shared user. This number may have more than 32 " +"Identifiers of the shared users. These numbers may have more than 32 " "significant bits and some programming languages may have " -"difficulty/silent defects in interpreting it. But it has at most 52 " -"significant bits, so a 64-bit integer or double-precision float type are " -"safe for storing this identifier. The bot may not have access to the user" -" and could be unable to use this identifier, unless the user is already " -"known to the bot by some other means." +"difficulty/silent defects in interpreting them. But they have at most 52 " +"significant bits, so 64-bit integers or double-precision float types are " +"safe for storing these identifiers. The bot may not have access to the " +"users and could be unable to use these identifiers unless the users are " +"already known to the bot by some other means." msgstr "" -#: of telebot.types.UserShared:16 -msgid ":class:`telebot.types.UserShared`" +#: of telebot.types.UsersShared:18 +msgid ":class:`UsersShared`" msgstr "" #: of telebot.types.Venue:1 @@ -6065,20 +7056,34 @@ msgstr "" #: of telebot.types.WriteAccessAllowed:1 msgid "" -"This object represents a service message about a user allowed to post " -"messages in the chat. Currently holds no information." +"This object represents a service message about a user allowing a bot to " +"write messages after adding it to the attachment menu, launching a Web " +"App from a link, or accepting an explicit request from a Web App sent by " +"the method requestWriteAccess." msgstr "" -#: of telebot.types.WriteAccessAllowed:4 +#: of telebot.types.WriteAccessAllowed:5 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#writeaccessallowed" msgstr "" -#: of telebot.types.WriteAccessAllowed:6 +#: of telebot.types.WriteAccessAllowed:7 +msgid "" +"Optional. True, if the access was granted after the user accepted an " +"explicit request from a Web App sent by the method requestWriteAccess" +msgstr "" + +#: of telebot.types.WriteAccessAllowed:11 msgid "Optional. Name of the Web App which was launched from a link" msgstr "" +#: of telebot.types.WriteAccessAllowed:14 +msgid "" +"Optional. True, if the access was granted when the bot was added to the " +"attachment or side menu" +msgstr "" + #~ msgid "Type of the result, must be animation" #~ msgstr "" @@ -6109,3 +7114,127 @@ msgstr "" #~ "can_send_media_messages" #~ msgstr "" +#~ msgid "" +#~ "Optional. Message with the callback " +#~ "button that originated the query. Note" +#~ " that message content and message " +#~ "date will not be available if the" +#~ " message is too old" +#~ msgstr "" + +#~ msgid "" +#~ "deprecated. True, if the user is " +#~ "allowed to send audios, documents, " +#~ "photos, videos, video notes and voice" +#~ " notes" +#~ msgstr "" + +#~ msgid "Optional. Disables link previews for links in the sent message" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. If specified, pressing the " +#~ "button will open a list of " +#~ "suitable users. Tapping on any user " +#~ "will send their identifier to the " +#~ "bot in a “user_shared” service message." +#~ " Available in private chats only." +#~ msgstr "" + +#~ msgid "" +#~ "Telegram documentation: " +#~ "https://core.telegram.org/bots/api#keyboardbuttonrequestuser" +#~ msgstr "" + +#~ msgid "" +#~ "Signed 32-bit identifier of the request," +#~ " which will be received back in " +#~ "the UserShared object. Must be unique" +#~ " within the message" +#~ msgstr "" + +#~ msgid ":class:`telebot.types.KeyboardButtonRequestUser`" +#~ msgstr "" + +#~ msgid "Optional. For forwarded messages, sender of the original message" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For messages forwarded from " +#~ "channels or from anonymous administrators, " +#~ "information about the original sender " +#~ "chat" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For messages forwarded from " +#~ "channels, identifier of the original " +#~ "message in the channel" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For forwarded messages that " +#~ "were originally sent in channels or " +#~ "by an anonymous chat administrator, " +#~ "signature of the message sender if " +#~ "present" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. Sender's name for messages " +#~ "forwarded from users who disallow adding" +#~ " a link to their account in " +#~ "forwarded messages" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For forwarded messages, date " +#~ "the original message was sent in " +#~ "Unix time" +#~ msgstr "" + +#~ msgid "The user, who changed the answer to the poll" +#~ msgstr "" + +#~ msgid "" +#~ "True, if the sticker set contains " +#~ "masks. Deprecated since Bot API 6.2, " +#~ "use sticker_type instead." +#~ msgstr "" + +#~ msgid "" +#~ "This object contains information about " +#~ "the user whose identifier was shared " +#~ "with the bot using a " +#~ "`telebot.types.KeyboardButtonRequestUser` button." +#~ msgstr "" + +#~ msgid "Telegram documentation: https://core.telegram.org/bots/api#usershared" +#~ msgstr "" + +#~ msgid "" +#~ "Identifier of the shared user. This " +#~ "number may have more than 32 " +#~ "significant bits and some programming " +#~ "languages may have difficulty/silent defects" +#~ " in interpreting it. But it has " +#~ "at most 52 significant bits, so a" +#~ " 64-bit integer or double-precision " +#~ "float type are safe for storing " +#~ "this identifier. The bot may not " +#~ "have access to the user and could" +#~ " be unable to use this identifier," +#~ " unless the user is already known " +#~ "to the bot by some other means." +#~ msgstr "" + +#~ msgid ":class:`telebot.types.UserShared`" +#~ msgstr "" + +#~ msgid "" +#~ "This object represents a service message" +#~ " about a user allowed to post " +#~ "messages in the chat. Currently holds" +#~ " no information." +#~ msgstr "" + diff --git a/docs/source/locales/ru/LC_MESSAGES/async_version.po b/docs/source/locales/ru/LC_MESSAGES/async_version.po index 8644f09fb..570c22026 100644 --- a/docs/source/locales/ru/LC_MESSAGES/async_version.po +++ b/docs/source/locales/ru/LC_MESSAGES/async_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-08 23:07+0500\n" +"POT-Creation-Date: 2024-01-05 22:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -89,12 +89,14 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.callback_query_handler #: telebot.async_telebot.AsyncTeleBot.channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.chat_member_handler #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler #: telebot.async_telebot.AsyncTeleBot.close_forum_topic #: telebot.async_telebot.AsyncTeleBot.close_general_forum_topic #: telebot.async_telebot.AsyncTeleBot.copy_message +#: telebot.async_telebot.AsyncTeleBot.copy_messages #: telebot.async_telebot.AsyncTeleBot.create_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.create_forum_topic #: telebot.async_telebot.AsyncTeleBot.create_invoice_link @@ -104,6 +106,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic #: telebot.async_telebot.AsyncTeleBot.delete_message +#: telebot.async_telebot.AsyncTeleBot.delete_messages #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set @@ -123,6 +126,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.enable_saving_states #: telebot.async_telebot.AsyncTeleBot.export_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.forward_message +#: telebot.async_telebot.AsyncTeleBot.forward_messages #: telebot.async_telebot.AsyncTeleBot.get_chat #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators #: telebot.async_telebot.AsyncTeleBot.get_chat_member @@ -140,6 +144,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos #: telebot.async_telebot.AsyncTeleBot.get_webhook_info #: telebot.async_telebot.AsyncTeleBot.hide_general_forum_topic @@ -147,6 +152,8 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.inline_handler #: telebot.async_telebot.AsyncTeleBot.leave_chat #: telebot.async_telebot.AsyncTeleBot.message_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.pin_chat_message #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler @@ -157,6 +164,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.promote_chat_member #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler @@ -164,11 +172,15 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler #: telebot.async_telebot.AsyncTeleBot.register_inline_handler #: telebot.async_telebot.AsyncTeleBot.register_message_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_handler #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic #: telebot.async_telebot.AsyncTeleBot.reopen_general_forum_topic #: telebot.async_telebot.AsyncTeleBot.reply_to @@ -204,6 +216,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.set_chat_title #: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights #: telebot.async_telebot.AsyncTeleBot.set_my_description @@ -227,6 +240,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.async_telebot.AsyncTeleBot.unhide_general_forum_topic #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message #: telebot.async_telebot.AsyncTeleBot.upload_sticker_file #: telebot.asyncio_filters.TextFilter @@ -300,12 +314,14 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.callback_query_handler #: telebot.async_telebot.AsyncTeleBot.channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.chat_member_handler #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler #: telebot.async_telebot.AsyncTeleBot.close #: telebot.async_telebot.AsyncTeleBot.close_forum_topic #: telebot.async_telebot.AsyncTeleBot.copy_message +#: telebot.async_telebot.AsyncTeleBot.copy_messages #: telebot.async_telebot.AsyncTeleBot.create_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.create_forum_topic #: telebot.async_telebot.AsyncTeleBot.create_invoice_link @@ -315,6 +331,7 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic #: telebot.async_telebot.AsyncTeleBot.delete_message +#: telebot.async_telebot.AsyncTeleBot.delete_messages #: telebot.async_telebot.AsyncTeleBot.delete_my_commands #: telebot.async_telebot.AsyncTeleBot.delete_state #: telebot.async_telebot.AsyncTeleBot.delete_sticker_from_set @@ -332,6 +349,7 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.edited_message_handler #: telebot.async_telebot.AsyncTeleBot.export_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.forward_message +#: telebot.async_telebot.AsyncTeleBot.forward_messages #: telebot.async_telebot.AsyncTeleBot.get_chat #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators #: telebot.async_telebot.AsyncTeleBot.get_chat_member @@ -350,6 +368,7 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos #: telebot.async_telebot.AsyncTeleBot.get_webhook_info #: telebot.async_telebot.AsyncTeleBot.infinity_polling @@ -357,6 +376,8 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.leave_chat #: telebot.async_telebot.AsyncTeleBot.log_out #: telebot.async_telebot.AsyncTeleBot.message_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.pin_chat_message #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler @@ -367,17 +388,22 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.promote_chat_member #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler #: telebot.async_telebot.AsyncTeleBot.register_edited_channel_post_handler #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler #: telebot.async_telebot.AsyncTeleBot.register_inline_handler #: telebot.async_telebot.AsyncTeleBot.register_message_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler #: telebot.async_telebot.AsyncTeleBot.register_poll_handler #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic #: telebot.async_telebot.AsyncTeleBot.reply_to #: telebot.async_telebot.AsyncTeleBot.reset_data @@ -412,6 +438,7 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.set_chat_title #: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail #: telebot.async_telebot.AsyncTeleBot.set_game_score +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction #: telebot.async_telebot.AsyncTeleBot.set_my_commands #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights #: telebot.async_telebot.AsyncTeleBot.set_my_description @@ -434,6 +461,7 @@ msgstr "Класс с методом check(message)" #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message #: telebot.async_telebot.AsyncTeleBot.upload_sticker_file #: telebot.asyncio_filters.TextFilter @@ -445,6 +473,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.add_data:10 #: telebot.async_telebot.AsyncTeleBot.callback_query_handler:9 #: telebot.async_telebot.AsyncTeleBot.channel_post_handler:17 +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler:8 #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:10 #: telebot.async_telebot.AsyncTeleBot.chat_member_handler:11 #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:10 @@ -459,14 +488,19 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.process_new_updates:8 #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:23 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:13 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:26 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:26 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:14 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:14 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:14 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:13 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:14 +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:8 #: telebot.async_telebot.AsyncTeleBot.reset_data:9 #: telebot.async_telebot.AsyncTeleBot.set_state:18 #: telebot.async_telebot.AsyncTeleBot.set_update_listener:15 @@ -599,6 +633,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_sticker_position_in_set:11 #: telebot.async_telebot.AsyncTeleBot.set_sticker_set_thumbnail:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:13 +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:11 msgid "On success, True is returned." msgstr "В случае успеха возвращается True." @@ -613,6 +648,7 @@ msgstr "В случае успеха возвращается True." #: telebot.async_telebot.AsyncTeleBot.ban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.close_forum_topic #: telebot.async_telebot.AsyncTeleBot.copy_message +#: telebot.async_telebot.AsyncTeleBot.copy_messages #: telebot.async_telebot.AsyncTeleBot.create_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.create_forum_topic #: telebot.async_telebot.AsyncTeleBot.create_invoice_link @@ -636,6 +672,7 @@ msgstr "В случае успеха возвращается True." #: telebot.async_telebot.AsyncTeleBot.edit_message_text #: telebot.async_telebot.AsyncTeleBot.export_chat_invite_link #: telebot.async_telebot.AsyncTeleBot.forward_message +#: telebot.async_telebot.AsyncTeleBot.forward_messages #: telebot.async_telebot.AsyncTeleBot.get_chat #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators #: telebot.async_telebot.AsyncTeleBot.get_chat_member @@ -650,6 +687,7 @@ msgstr "В случае успеха возвращается True." #: telebot.async_telebot.AsyncTeleBot.get_state #: telebot.async_telebot.AsyncTeleBot.get_sticker_set #: telebot.async_telebot.AsyncTeleBot.get_updates +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos #: telebot.async_telebot.AsyncTeleBot.get_webhook_info #: telebot.async_telebot.AsyncTeleBot.log_out @@ -701,6 +739,7 @@ msgstr "В случае успеха возвращается True." #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message #: telebot.async_telebot.AsyncTeleBot.upload_sticker_file msgid "Return type" @@ -730,7 +769,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.leave_chat:8 #: telebot.async_telebot.AsyncTeleBot.log_out:11 #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:19 -#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:61 +#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:70 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:14 #: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:61 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:26 @@ -741,6 +780,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.set_chat_photo:16 #: telebot.async_telebot.AsyncTeleBot.set_chat_title:17 #: telebot.async_telebot.AsyncTeleBot.set_custom_emoji_sticker_set_thumbnail:11 +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction:18 #: telebot.async_telebot.AsyncTeleBot.set_my_commands:18 #: telebot.async_telebot.AsyncTeleBot.set_my_default_administrator_rights:18 #: telebot.async_telebot.AsyncTeleBot.set_sticker_emoji_list:11 @@ -753,6 +793,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.unban_chat_sender_chat:15 #: telebot.async_telebot.AsyncTeleBot.unpin_all_chat_messages:12 #: telebot.async_telebot.AsyncTeleBot.unpin_all_forum_topic_messages:14 +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:12 #: telebot.async_telebot.AsyncTeleBot.unpin_chat_message:15 msgid ":obj:`bool`" msgstr "" @@ -1074,6 +1115,7 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.ban_chat_member:12 #: telebot.async_telebot.AsyncTeleBot.decline_chat_join_request:11 #: telebot.async_telebot.AsyncTeleBot.get_chat_member:8 +#: telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:8 #: telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:6 #: telebot.async_telebot.AsyncTeleBot.promote_chat_member:11 #: telebot.async_telebot.AsyncTeleBot.restrict_chat_member:14 @@ -1089,7 +1131,7 @@ msgstr "Уникальный id сделавшего запрос пользов #: telebot.async_telebot.AsyncTeleBot.delete_my_commands:16 #: telebot.async_telebot.AsyncTeleBot.log_out:10 #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:18 -#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:60 +#: telebot.async_telebot.AsyncTeleBot.promote_chat_member:69 #: telebot.async_telebot.AsyncTeleBot.set_chat_administrator_custom_title:17 #: telebot.async_telebot.AsyncTeleBot.set_chat_description:13 #: telebot.async_telebot.AsyncTeleBot.set_chat_menu_button:14 @@ -1156,6 +1198,7 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.ban_chat_member:24 #: telebot.async_telebot.AsyncTeleBot.delete_chat_sticker_set:10 #: telebot.async_telebot.AsyncTeleBot.delete_message:22 +#: telebot.async_telebot.AsyncTeleBot.delete_messages:14 #: telebot.async_telebot.AsyncTeleBot.delete_sticker_set:6 #: telebot.async_telebot.AsyncTeleBot.delete_webhook:12 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:25 @@ -1192,13 +1235,16 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.close_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.close_general_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.copy_message:5 +#: telebot.async_telebot.AsyncTeleBot.copy_messages:3 #: telebot.async_telebot.AsyncTeleBot.create_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.delete_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.delete_message:13 +#: telebot.async_telebot.AsyncTeleBot.delete_messages:8 #: telebot.async_telebot.AsyncTeleBot.edit_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.edit_general_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.edit_message_live_location:13 #: telebot.async_telebot.AsyncTeleBot.forward_message:8 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:3 #: telebot.async_telebot.AsyncTeleBot.hide_general_forum_topic:7 #: telebot.async_telebot.AsyncTeleBot.pin_chat_message:7 #: telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:7 @@ -1242,18 +1288,22 @@ msgstr "" #: of telebot.async_telebot.AsyncTeleBot.callback_query_handler:4 #: telebot.async_telebot.AsyncTeleBot.channel_post_handler:10 +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler:4 #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:5 #: telebot.async_telebot.AsyncTeleBot.chat_member_handler:6 #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:5 #: telebot.async_telebot.AsyncTeleBot.edited_channel_post_handler:10 #: telebot.async_telebot.AsyncTeleBot.edited_message_handler:11 #: telebot.async_telebot.AsyncTeleBot.inline_handler:4 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler:4 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler:4 #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler:5 #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler:5 #: telebot.async_telebot.AsyncTeleBot.poll_handler:4 #: telebot.async_telebot.AsyncTeleBot.pre_checkout_query_handler:4 #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:15 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:6 @@ -1261,17 +1311,22 @@ msgstr "" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:15 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:15 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:6 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:6 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:6 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:6 +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:4 #: telebot.async_telebot.AsyncTeleBot.shipping_query_handler:4 msgid "Function executed as a filter" msgstr "Функция, используемая в качестве фильтра" #: of telebot.async_telebot.AsyncTeleBot.callback_query_handler:7 #: telebot.async_telebot.AsyncTeleBot.channel_post_handler:16 +#: telebot.async_telebot.AsyncTeleBot.chat_boost_handler:7 #: telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:8 #: telebot.async_telebot.AsyncTeleBot.chat_member_handler:9 #: telebot.async_telebot.AsyncTeleBot.chosen_inline_handler:8 @@ -1279,12 +1334,15 @@ msgstr "Функция, используемая в качестве фильт #: telebot.async_telebot.AsyncTeleBot.edited_message_handler:20 #: telebot.async_telebot.AsyncTeleBot.inline_handler:7 #: telebot.async_telebot.AsyncTeleBot.message_handler:50 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler:7 +#: telebot.async_telebot.AsyncTeleBot.message_reaction_handler:7 #: telebot.async_telebot.AsyncTeleBot.my_chat_member_handler:8 #: telebot.async_telebot.AsyncTeleBot.poll_answer_handler:8 #: telebot.async_telebot.AsyncTeleBot.poll_handler:7 #: telebot.async_telebot.AsyncTeleBot.pre_checkout_query_handler:7 #: telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:21 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:11 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:12 @@ -1292,11 +1350,15 @@ msgstr "Функция, используемая в качестве фильт #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:24 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:24 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:12 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:12 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:11 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:11 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:12 +#: telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:7 #: telebot.async_telebot.AsyncTeleBot.shipping_query_handler:7 msgid "Optional keyword arguments(custom filters)" msgstr "Необязательные именованные аргументы(кастомные фильтры)" @@ -1336,6 +1398,15 @@ msgstr "Необязательное регулярное выражение." msgid "Supported message content types. Must be a list. Defaults to ['text']." msgstr "Обрабатываемые виды контента. Обязан быть списком. По умолчанию ['text']" +#: of telebot.async_telebot.AsyncTeleBot.chat_boost_handler:1 +#, fuzzy +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostUpdated` object." +msgstr "" +"Обрабатывает новый callback запрос. В качестве параметра передаёт в " +"декорируемую функцию объект :class:`telebot.types.CallbackQuery`." + #: of telebot.async_telebot.AsyncTeleBot.chat_join_request_handler:1 msgid "" "Handles a request to join the chat has been sent. The bot must have the " @@ -1439,6 +1510,7 @@ msgstr "" "работы поллинга или вебхука." #: of telebot.async_telebot.AsyncTeleBot.copy_message:1 +#: telebot.async_telebot.AsyncTeleBot.copy_messages:1 msgid "Use this method to copy messages of any kind." msgstr "Используйте этот метод для копирования любых сообщений." @@ -1447,7 +1519,9 @@ msgid "Telegram documentation: https://core.telegram.org/bots/api#copymessage" msgstr "Документация Telegram: https://core.telegram.org/bots/api#copymessage" #: of telebot.async_telebot.AsyncTeleBot.copy_message:8 +#: telebot.async_telebot.AsyncTeleBot.copy_messages:6 #: telebot.async_telebot.AsyncTeleBot.forward_message:11 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:6 msgid "" "Unique identifier for the chat where the original message was sent (or " "channel username in the format @channelusername)" @@ -1621,8 +1695,6 @@ msgid "Identifier of a message thread, in which the message will be sent" msgstr "id топика, в который нужно отправить сообщение" #: of telebot.async_telebot.AsyncTeleBot.copy_message:45 -#: telebot.async_telebot.AsyncTeleBot.forward_message:26 -#: telebot.async_telebot.AsyncTeleBot.reply_to:11 #: telebot.async_telebot.AsyncTeleBot.send_animation:66 #: telebot.async_telebot.AsyncTeleBot.send_audio:66 #: telebot.async_telebot.AsyncTeleBot.send_contact:44 @@ -1631,6 +1703,7 @@ msgstr "id топика, в который нужно отправить соо #: telebot.async_telebot.AsyncTeleBot.send_game:32 #: telebot.async_telebot.AsyncTeleBot.send_invoice:101 #: telebot.async_telebot.AsyncTeleBot.send_location:49 +#: telebot.async_telebot.AsyncTeleBot.send_media_group:30 #: telebot.async_telebot.AsyncTeleBot.send_message:46 #: telebot.async_telebot.AsyncTeleBot.send_photo:48 #: telebot.async_telebot.AsyncTeleBot.send_poll:70 @@ -1639,26 +1712,61 @@ msgstr "id топика, в который нужно отправить соо #: telebot.async_telebot.AsyncTeleBot.send_video:67 #: telebot.async_telebot.AsyncTeleBot.send_video_note:51 #: telebot.async_telebot.AsyncTeleBot.send_voice:49 -msgid "On success, the sent Message is returned." +msgid "Reply parameters." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_message:48 +#, fuzzy +msgid "On success, the MessageId of the sent message is returned." msgstr "В случае успеха возвращает отправленное сообщение (Message)." -#: of telebot.async_telebot.AsyncTeleBot.copy_message:46 -#: telebot.async_telebot.AsyncTeleBot.forward_message:27 -#: telebot.async_telebot.AsyncTeleBot.reply_to:12 -#: telebot.async_telebot.AsyncTeleBot.send_animation:67 -#: telebot.async_telebot.AsyncTeleBot.send_audio:67 -#: telebot.async_telebot.AsyncTeleBot.send_contact:45 -#: telebot.async_telebot.AsyncTeleBot.send_dice:36 -#: telebot.async_telebot.AsyncTeleBot.send_document:60 -#: telebot.async_telebot.AsyncTeleBot.send_location:50 -#: telebot.async_telebot.AsyncTeleBot.send_message:47 -#: telebot.async_telebot.AsyncTeleBot.send_photo:49 -#: telebot.async_telebot.AsyncTeleBot.send_sticker:43 -#: telebot.async_telebot.AsyncTeleBot.send_venue:58 -#: telebot.async_telebot.AsyncTeleBot.send_video:68 -#: telebot.async_telebot.AsyncTeleBot.send_video_note:52 -msgid ":class:`telebot.types.Message`" +#: of telebot.async_telebot.AsyncTeleBot.copy_message:49 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:22 +#, fuzzy +msgid ":class:`telebot.types.MessageID`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:9 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:9 +#, fuzzy +msgid "Message identifiers in the chat specified in from_chat_id" +msgstr "id сообщения в чате, заданном в from_chat_id" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:12 +#: telebot.async_telebot.AsyncTeleBot.forward_message:5 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:12 +msgid "" +"Sends the message silently. Users will receive a notification with no " +"sound" msgstr "" +"Отправить сообщение, при получении которого пользователи получат " +"уведомление без звука" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:15 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:15 +#: telebot.async_telebot.AsyncTeleBot.send_media_group:27 +msgid "Identifier of a message thread, in which the messages will be sent" +msgstr "id топика, в который будет отправлена группа медиа" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:18 +#: telebot.async_telebot.AsyncTeleBot.forward_message:17 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:18 +msgid "Protects the contents of the forwarded message from forwarding and saving" +msgstr "Запретить пересылку и сохранение содержимого пересланного сообщения" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:21 +msgid "Pass True to copy the messages without their captions" +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:24 +#, fuzzy +msgid "On success, an array of MessageId of the sent messages is returned." +msgstr "В случае успеха возвращает отправленное сообщение (Message)." + +#: of telebot.async_telebot.AsyncTeleBot.copy_messages:25 +#, fuzzy +msgid ":obj:`list` of :class:`telebot.types.MessageID`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" #: of telebot.async_telebot.AsyncTeleBot.create_chat_invite_link:1 msgid "" @@ -2137,6 +2245,24 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#de msgid "Identifier of the message to delete" msgstr "id сообщения, которое нужно удалить" +#: of telebot.async_telebot.AsyncTeleBot.delete_messages:1 +msgid "" +"Use this method to delete multiple messages in a chat. The number of " +"messages to be deleted must not exceed 100. If the chat is a private " +"chat, the user must be an administrator of the chat for this to work and " +"must have the appropriate admin rights. Returns True on success." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.delete_messages:6 +#, fuzzy +msgid "Telegram documentation: https://core.telegram.org/bots/api#deletemessages" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#deletemessage" + +#: of telebot.async_telebot.AsyncTeleBot.delete_messages:11 +#, fuzzy +msgid "Identifiers of the messages to be deleted" +msgstr "id сообщения, которое нужно удалить" + #: of telebot.async_telebot.AsyncTeleBot.delete_my_commands:1 msgid "" "Use this method to delete the list of the bot's commands for the given " @@ -2385,7 +2511,7 @@ msgstr "JSON-сериализованный объект inline клавиату #: of telebot.async_telebot.AsyncTeleBot.edit_message_caption:26 #: telebot.async_telebot.AsyncTeleBot.edit_message_media:22 #: telebot.async_telebot.AsyncTeleBot.edit_message_reply_markup:17 -#: telebot.async_telebot.AsyncTeleBot.edit_message_text:29 +#: telebot.async_telebot.AsyncTeleBot.edit_message_text:32 msgid "" "On success, if edited message is sent by the bot, the edited Message is " "returned, otherwise True is returned." @@ -2538,7 +2664,7 @@ msgstr "Обязательный, если не указан inline_message_id. #: of telebot.async_telebot.AsyncTeleBot.edit_message_media:23 #: telebot.async_telebot.AsyncTeleBot.edit_message_reply_markup:18 -#: telebot.async_telebot.AsyncTeleBot.edit_message_text:30 +#: telebot.async_telebot.AsyncTeleBot.edit_message_text:33 #: telebot.async_telebot.AsyncTeleBot.set_game_score:27 msgid ":obj:`types.Message` or :obj:`bool`" msgstr "" @@ -2585,6 +2711,12 @@ msgstr "" msgid "Disables link previews for links in this message" msgstr "Отключает превью ссылок в сообщении" +#: of telebot.async_telebot.AsyncTeleBot.edit_message_text:29 +msgid "" +"A JSON-serialized object for options used to automatically generate " +"Telegram link previews for messages." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.edited_channel_post_handler:1 msgid "" "Handles new version of a channel post that is known to the bot and was " @@ -2655,6 +2787,7 @@ msgid "exported invite link as String on success." msgstr "новая ссылка-приглашение (String) в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.forward_message:1 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:1 msgid "Use this method to forward messages of any kind." msgstr "Используйте этот метод, чтобы переслать любое сообщение." @@ -2662,18 +2795,6 @@ msgstr "Используйте этот метод, чтобы переслат msgid "Telegram documentation: https://core.telegram.org/bots/api#forwardmessage" msgstr "Документация Telegram: https://core.telegram.org/bots/api#forwardmessage" -#: of telebot.async_telebot.AsyncTeleBot.forward_message:5 -msgid "" -"Sends the message silently. Users will receive a notification with no " -"sound" -msgstr "" -"Отправить сообщение, при получении которого пользователи получат " -"уведомление без звука" - -#: of telebot.async_telebot.AsyncTeleBot.forward_message:17 -msgid "Protects the contents of the forwarded message from forwarding and saving" -msgstr "Запретить пересылку и сохранение содержимого пересланного сообщения" - #: of telebot.async_telebot.AsyncTeleBot.forward_message:23 #: telebot.async_telebot.AsyncTeleBot.send_message:43 msgid "" @@ -2683,6 +2804,45 @@ msgstr "" "Уникальный id топика, в который нужно переслать сообщение; только для " "супергрупп с топиками" +#: of telebot.async_telebot.AsyncTeleBot.forward_message:26 +#: telebot.async_telebot.AsyncTeleBot.forward_messages:21 +#: telebot.async_telebot.AsyncTeleBot.reply_to:11 +#: telebot.async_telebot.AsyncTeleBot.send_animation:69 +#: telebot.async_telebot.AsyncTeleBot.send_audio:69 +#: telebot.async_telebot.AsyncTeleBot.send_contact:47 +#: telebot.async_telebot.AsyncTeleBot.send_dice:38 +#: telebot.async_telebot.AsyncTeleBot.send_document:62 +#: telebot.async_telebot.AsyncTeleBot.send_game:35 +#: telebot.async_telebot.AsyncTeleBot.send_invoice:104 +#: telebot.async_telebot.AsyncTeleBot.send_location:52 +#: telebot.async_telebot.AsyncTeleBot.send_message:52 +#: telebot.async_telebot.AsyncTeleBot.send_photo:51 +#: telebot.async_telebot.AsyncTeleBot.send_poll:73 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:45 +#: telebot.async_telebot.AsyncTeleBot.send_venue:60 +#: telebot.async_telebot.AsyncTeleBot.send_video:70 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:54 +#: telebot.async_telebot.AsyncTeleBot.send_voice:52 +msgid "On success, the sent Message is returned." +msgstr "В случае успеха возвращает отправленное сообщение (Message)." + +#: of telebot.async_telebot.AsyncTeleBot.forward_message:27 +#: telebot.async_telebot.AsyncTeleBot.reply_to:12 +#: telebot.async_telebot.AsyncTeleBot.send_animation:70 +#: telebot.async_telebot.AsyncTeleBot.send_audio:70 +#: telebot.async_telebot.AsyncTeleBot.send_contact:48 +#: telebot.async_telebot.AsyncTeleBot.send_dice:39 +#: telebot.async_telebot.AsyncTeleBot.send_document:63 +#: telebot.async_telebot.AsyncTeleBot.send_location:53 +#: telebot.async_telebot.AsyncTeleBot.send_message:53 +#: telebot.async_telebot.AsyncTeleBot.send_photo:52 +#: telebot.async_telebot.AsyncTeleBot.send_sticker:46 +#: telebot.async_telebot.AsyncTeleBot.send_venue:61 +#: telebot.async_telebot.AsyncTeleBot.send_video:71 +#: telebot.async_telebot.AsyncTeleBot.send_video_note:55 +msgid ":class:`telebot.types.Message`" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.get_chat:1 msgid "" "Use this method to get up to date information about the chat (current " @@ -2702,6 +2862,7 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#ge #: telebot.async_telebot.AsyncTeleBot.get_chat_administrators:7 #: telebot.async_telebot.AsyncTeleBot.get_chat_member_count:5 #: telebot.async_telebot.AsyncTeleBot.leave_chat:5 +#: telebot.async_telebot.AsyncTeleBot.set_message_reaction:5 msgid "" "Unique identifier for the target chat or username of the target " "supergroup or channel (in the format @channelusername)" @@ -3160,6 +3321,43 @@ msgstr "Возвращается массив объектов Update." msgid ":obj:`list` of :class:`telebot.types.Update`" msgstr "" +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:1 +#, fuzzy +msgid "" +"Use this method to get the list of boosts added to a chat by a user. " +"Requires administrator rights in the chat. Returns a UserChatBoosts " +"object." +msgstr "" +"Используйте этот метод, чтобы получить текущие права администратора для " +"бота по умолчанию. Возвращает объект ChatAdministratorRights в случае " +"успеха." + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:3 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getuserchatboosts" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#getchat" + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:5 +#: telebot.async_telebot.AsyncTeleBot.send_chat_action:10 +#: telebot.async_telebot.AsyncTeleBot.send_contact:5 +#: telebot.async_telebot.AsyncTeleBot.send_poll:6 +#: telebot.async_telebot.AsyncTeleBot.send_venue:5 +#: telebot.async_telebot.AsyncTeleBot.stop_poll:5 +msgid "Unique identifier for the target chat or username of the target channel" +msgstr "Уникальный id чата или username канала" + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:11 +#, fuzzy +msgid "On success, a UserChatBoosts object is returned." +msgstr "В случае успеха, возвращается объект StickerSet." + +#: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:12 +#, fuzzy +msgid ":class:`telebot.types.UserChatBoosts`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + #: of telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:1 msgid "" "Use this method to get a list of profile pictures for a user. Returns a " @@ -3407,6 +3605,25 @@ msgstr "" msgid "decorated function" msgstr "декорируемая функция" +#: of telebot.async_telebot.AsyncTeleBot.message_reaction_count_handler:1 +#, fuzzy +msgid "" +"Handles new incoming message reaction count. As a parameter to the " +"decorator function, it passes " +":class:`telebot.types.MessageReactionCountUpdated` object." +msgstr "" +"Обрабатывает новый callback запрос. В качестве параметра передаёт в " +"декорируемую функцию объект :class:`telebot.types.CallbackQuery`." + +#: of telebot.async_telebot.AsyncTeleBot.message_reaction_handler:1 +#, fuzzy +msgid "" +"Handles new incoming message reaction. As a parameter to the decorator " +"function, it passes :class:`telebot.types.MessageReactionUpdated` object." +msgstr "" +"Обрабатывает новый callback запрос. В качестве параметра передаёт в " +"декорируемую функцию объект :class:`telebot.types.CallbackQuery`." + #: of telebot.async_telebot.AsyncTeleBot.my_chat_member_handler:1 msgid "" "Handles update in a status of a bot. For private chats, this update is " @@ -3655,12 +3872,34 @@ msgstr "" "Передайте True, если пользователю разрешено создавать, переименовывать, " "закрывать, и возобновлять топики, только для супергрупп" +#: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:60 +#, fuzzy +msgid "Pass True if the administrator can create the channel's stories" +msgstr "" +"Передайте True, если администратор может создавать посты в канале, только" +" для каналов" + +#: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:63 +#, fuzzy +msgid "Pass True if the administrator can edit the channel's stories" +msgstr "" +"Передайте True, если администратор может изменять сообщения других " +"пользователей, только для каналов" + +#: of telebot.async_telebot.AsyncTeleBot.promote_chat_member:66 +#, fuzzy +msgid "Pass True if the administrator can delete the channel's stories" +msgstr "" +"Передайте True, если администратор может создавать посты в канале, только" +" для каналов" + #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:1 msgid "Registers callback query handler." msgstr "Регистрирует хендлер callback query." #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:3 @@ -3668,16 +3907,20 @@ msgstr "Регистрирует хендлер callback query." #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:3 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:3 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:3 msgid "function to be called" msgstr "функция-хендлер" #: of telebot.async_telebot.AsyncTeleBot.register_callback_query_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_channel_post_handler:18 +#: telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_chat_member_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_chosen_inline_handler:9 @@ -3685,10 +3928,13 @@ msgstr "функция-хендлер" #: telebot.async_telebot.AsyncTeleBot.register_edited_message_handler:21 #: telebot.async_telebot.AsyncTeleBot.register_inline_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_message_handler:21 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:9 +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_poll_answer_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_poll_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_pre_checkout_query_handler:8 +#: telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:9 #: telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:9 msgid "" "True if you need to pass TeleBot instance to handler(useful for " @@ -3714,6 +3960,11 @@ msgstr "список команд" msgid "Regular expression" msgstr "Регулярное выражение" +#: of telebot.async_telebot.AsyncTeleBot.register_chat_boost_handler:1 +#, fuzzy +msgid "Registers chat boost handler." +msgstr "Регистрирует хендлер смены состояний участников чата." + #: of telebot.async_telebot.AsyncTeleBot.register_chat_join_request_handler:1 msgid "Registers chat join request handler." msgstr "Регистрирует хендлер запросов на вступление в чат." @@ -3754,6 +4005,17 @@ msgstr "Регистрирует хендлер сообщений." msgid "List of chat types" msgstr "Список видов чатов" +#: of +#: telebot.async_telebot.AsyncTeleBot.register_message_reaction_count_handler:1 +#, fuzzy +msgid "Registers message reaction count handler." +msgstr "Регистрирует хендлер сообщений." + +#: of telebot.async_telebot.AsyncTeleBot.register_message_reaction_handler:1 +#, fuzzy +msgid "Registers message reaction handler." +msgstr "Регистрирует хендлер сообщений." + #: of telebot.async_telebot.AsyncTeleBot.register_my_chat_member_handler:1 msgid "Registers my chat member handler." msgstr "Регистрирует хендлер изменений статуса бота." @@ -3770,6 +4032,11 @@ msgstr "Регистрирует хендлер изменений состоя msgid "Registers pre-checkout request handler." msgstr "Регистрирует хендлер pre-checkout query." +#: of telebot.async_telebot.AsyncTeleBot.register_removed_chat_boost_handler:1 +#, fuzzy +msgid "Registers removed chat boost handler." +msgstr "Регистрирует хендлер изменений статуса бота." + #: of telebot.async_telebot.AsyncTeleBot.register_shipping_query_handler:1 msgid "Registers shipping query handler." msgstr "Регистрирует хендлер shipping query." @@ -3778,6 +4045,15 @@ msgstr "Регистрирует хендлер shipping query." msgid "Alternative for delete_webhook but uses set_webhook" msgstr "Альтернатива delete_webhook, но использует set_webhook" +#: of telebot.async_telebot.AsyncTeleBot.removed_chat_boost_handler:1 +#, fuzzy +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostRemoved` object." +msgstr "" +"Обрабатывает inline query. В качестве параметра, передаёт в декорируемую " +"функцию объект :class:`telebot.types.InlineQuery`." + #: of telebot.async_telebot.AsyncTeleBot.reopen_forum_topic:1 msgid "" "Use this method to reopen a closed topic in a forum supergroup chat. The " @@ -4309,14 +4585,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendchataction" msgstr "Документация Telegram: https://core.telegram.org/bots/api#sendchataction" -#: of telebot.async_telebot.AsyncTeleBot.send_chat_action:10 -#: telebot.async_telebot.AsyncTeleBot.send_contact:5 -#: telebot.async_telebot.AsyncTeleBot.send_poll:6 -#: telebot.async_telebot.AsyncTeleBot.send_venue:5 -#: telebot.async_telebot.AsyncTeleBot.stop_poll:5 -msgid "Unique identifier for the target chat or username of the target channel" -msgstr "Уникальный id чата или username канала" - #: of telebot.async_telebot.AsyncTeleBot.send_chat_action:13 msgid "" "Type of action to broadcast. Choose one, depending on what the user is " @@ -4520,9 +4788,9 @@ msgstr "" msgid "Identifier of the thread to which the message will be sent." msgstr "id топика, в которые будет сообщение будет отправлено." -#: of telebot.async_telebot.AsyncTeleBot.send_game:33 -#: telebot.async_telebot.AsyncTeleBot.send_invoice:102 -#: telebot.async_telebot.AsyncTeleBot.send_poll:71 +#: of telebot.async_telebot.AsyncTeleBot.send_game:36 +#: telebot.async_telebot.AsyncTeleBot.send_invoice:105 +#: telebot.async_telebot.AsyncTeleBot.send_poll:74 msgid ":obj:`types.Message`" msgstr "" @@ -4654,11 +4922,7 @@ msgstr "" "Отправить сообщение, при получении которого пользователя пользователи " "получат уведомление без звука." -#: of telebot.async_telebot.AsyncTeleBot.send_media_group:27 -msgid "Identifier of a message thread, in which the messages will be sent" -msgstr "id топика, в который будет отправлена группа медиа" - -#: of telebot.async_telebot.AsyncTeleBot.send_media_group:30 +#: of telebot.async_telebot.AsyncTeleBot.send_media_group:33 msgid "On success, an array of Messages that were sent is returned." msgstr "В случае успеха, возвращается массив отправленных сообщений (Message)." @@ -4701,6 +4965,10 @@ msgstr "" "Если True, содержимое сообщения будет скрыто от всех пользователей, кроме" " заданного" +#: of telebot.async_telebot.AsyncTeleBot.send_message:49 +msgid "Options for previewing links." +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.send_photo:1 msgid "Use this method to send photos. On success, the sent Message is returned." msgstr "" @@ -5298,6 +5566,43 @@ msgstr "" "В случае успеха, если сообщение было отправлено ботом, возвращает " "измененное сообщение (Message), иначе возвращает True." +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:1 +#, fuzzy +msgid "" +"Use this method to set a reaction to a message in a chat. The bot must be" +" an administrator in the chat for this to work and must have the " +"appropriate admin rights. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы закрепить сообщение в супергруппе. Бот " +"должен быть администратором чата и иметь соответствующие права " +"администратора. Возвращает True в случае успеха." + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:3 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmessagereaction" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#editmessagecaption" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:8 +#, fuzzy +msgid "Identifier of the message to set reaction to" +msgstr "id сообщения, которое нужно удалить" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:11 +msgid "" +"New list of reaction types to set on the message. Currently, as non-" +"premium users, bots can set up to one reaction per message. A custom " +"emoji reaction can be used if it is either already present on the message" +" or explicitly allowed by chat administrators." +msgstr "" + +#: of telebot.async_telebot.AsyncTeleBot.set_message_reaction:15 +msgid "Pass True to set the reaction with a big animation" +msgstr "" + #: of telebot.async_telebot.AsyncTeleBot.set_my_commands:1 msgid "Use this method to change the list of the bot's commands." msgstr "Используйте этот метод, чтобы изменить список команд бота." @@ -5937,6 +6242,35 @@ msgstr "" msgid "Identifier of the topic" msgstr "id топика" +#: of +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:1 +#, fuzzy +msgid "" +"Use this method to clear the list of pinned messages in a General forum " +"topic. The bot must be an administrator in the chat for this to work and " +"must have the can_pin_messages administrator right in the supergroup. " +"Returns True on success." +msgstr "" +"Используйте этот метод, что открепить все закрепленные сообщения в " +"топике. Бот должен быть администратором чата и иметь права администратора" +" can_pin_messages в супергруппе. Возвращает True в случае успеха." + +#: of +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:6 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#unpinallforumtopicmessages" + +#: of +#: telebot.async_telebot.AsyncTeleBot.unpin_all_general_forum_topic_messages:8 +#, fuzzy +msgid "Unique identifier for the target chat or username of chat" +msgstr "Уникальный id чата или username канала" + #: of telebot.async_telebot.AsyncTeleBot.unpin_chat_message:1 msgid "" "Use this method to unpin specific pinned message in a supergroup chat. " diff --git a/docs/source/locales/ru/LC_MESSAGES/sync_version.po b/docs/source/locales/ru/LC_MESSAGES/sync_version.po index c9243db70..e304f04ad 100644 --- a/docs/source/locales/ru/LC_MESSAGES/sync_version.po +++ b/docs/source/locales/ru/LC_MESSAGES/sync_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-08 23:07+0500\n" +"POT-Creation-Date: 2024-01-05 22:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -100,7 +100,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.answer_shipping_query telebot.TeleBot.answer_web_app_query #: telebot.TeleBot.approve_chat_join_request telebot.TeleBot.ban_chat_member #: telebot.TeleBot.ban_chat_sender_chat telebot.TeleBot.callback_query_handler -#: telebot.TeleBot.channel_post_handler +#: telebot.TeleBot.channel_post_handler telebot.TeleBot.chat_boost_handler #: telebot.TeleBot.chat_join_request_handler #: telebot.TeleBot.chat_member_handler telebot.TeleBot.chosen_inline_handler #: telebot.TeleBot.clear_reply_handlers @@ -108,16 +108,17 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.clear_step_handler #: telebot.TeleBot.clear_step_handler_by_chat_id #: telebot.TeleBot.close_forum_topic telebot.TeleBot.close_general_forum_topic -#: telebot.TeleBot.copy_message telebot.TeleBot.create_chat_invite_link -#: telebot.TeleBot.create_forum_topic telebot.TeleBot.create_invoice_link -#: telebot.TeleBot.create_new_sticker_set +#: telebot.TeleBot.copy_message telebot.TeleBot.copy_messages +#: telebot.TeleBot.create_chat_invite_link telebot.TeleBot.create_forum_topic +#: telebot.TeleBot.create_invoice_link telebot.TeleBot.create_new_sticker_set #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic -#: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands -#: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook -#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link -#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_general_forum_topic +#: telebot.TeleBot.delete_message telebot.TeleBot.delete_messages +#: telebot.TeleBot.delete_my_commands telebot.TeleBot.delete_state +#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_sticker_set +#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file +#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic +#: telebot.TeleBot.edit_general_forum_topic #: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup @@ -127,9 +128,10 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.enable_save_next_step_handlers #: telebot.TeleBot.enable_save_reply_handlers #: telebot.TeleBot.enable_saving_states telebot.TeleBot.export_chat_invite_link -#: telebot.TeleBot.forward_message telebot.TeleBot.get_chat -#: telebot.TeleBot.get_chat_administrators telebot.TeleBot.get_chat_member -#: telebot.TeleBot.get_chat_member_count telebot.TeleBot.get_chat_menu_button +#: telebot.TeleBot.forward_message telebot.TeleBot.forward_messages +#: telebot.TeleBot.get_chat telebot.TeleBot.get_chat_administrators +#: telebot.TeleBot.get_chat_member telebot.TeleBot.get_chat_member_count +#: telebot.TeleBot.get_chat_menu_button #: telebot.TeleBot.get_custom_emoji_stickers telebot.TeleBot.get_file #: telebot.TeleBot.get_file_url telebot.TeleBot.get_game_high_scores #: telebot.TeleBot.get_my_commands @@ -137,17 +139,20 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name #: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state #: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates -#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info -#: telebot.TeleBot.hide_general_forum_topic telebot.TeleBot.infinity_polling -#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat -#: telebot.TeleBot.load_next_step_handlers telebot.TeleBot.load_reply_handlers -#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.get_user_chat_boosts telebot.TeleBot.get_user_profile_photos +#: telebot.TeleBot.get_webhook_info telebot.TeleBot.hide_general_forum_topic +#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler +#: telebot.TeleBot.leave_chat telebot.TeleBot.load_next_step_handlers +#: telebot.TeleBot.load_reply_handlers telebot.TeleBot.message_handler +#: telebot.TeleBot.message_reaction_count_handler +#: telebot.TeleBot.message_reaction_handler telebot.TeleBot.middleware_handler #: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message #: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler #: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.process_new_updates telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler +#: telebot.TeleBot.register_chat_boost_handler #: telebot.TeleBot.register_chat_join_request_handler #: telebot.TeleBot.register_chat_member_handler #: telebot.TeleBot.register_chosen_inline_handler @@ -157,6 +162,8 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.register_for_reply_by_message_id #: telebot.TeleBot.register_inline_handler #: telebot.TeleBot.register_message_handler +#: telebot.TeleBot.register_message_reaction_count_handler +#: telebot.TeleBot.register_message_reaction_handler #: telebot.TeleBot.register_middleware_handler #: telebot.TeleBot.register_my_chat_member_handler #: telebot.TeleBot.register_next_step_handler @@ -164,7 +171,9 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.register_poll_answer_handler #: telebot.TeleBot.register_poll_handler #: telebot.TeleBot.register_pre_checkout_query_handler +#: telebot.TeleBot.register_removed_chat_boost_handler #: telebot.TeleBot.register_shipping_query_handler +#: telebot.TeleBot.removed_chat_boost_handler #: telebot.TeleBot.reopen_forum_topic #: telebot.TeleBot.reopen_general_forum_topic telebot.TeleBot.reply_to #: telebot.TeleBot.reset_data telebot.TeleBot.restrict_chat_member @@ -177,13 +186,15 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.send_media_group telebot.TeleBot.send_message #: telebot.TeleBot.send_photo telebot.TeleBot.send_poll #: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_voice +#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note +#: telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail -#: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands +#: telebot.TeleBot.set_game_score telebot.TeleBot.set_message_reaction +#: telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights #: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name #: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state @@ -199,6 +210,7 @@ msgstr "Установите пакет coloredlogs для использова #: telebot.TeleBot.unhide_general_forum_topic #: telebot.TeleBot.unpin_all_chat_messages #: telebot.TeleBot.unpin_all_forum_topic_messages +#: telebot.TeleBot.unpin_all_general_forum_topic_messages #: telebot.TeleBot.unpin_chat_message telebot.TeleBot.upload_sticker_file #: telebot.custom_filters.TextFilter msgid "Parameters" @@ -314,7 +326,7 @@ msgstr "Данные для добавления" #: telebot.TeleBot.answer_shipping_query telebot.TeleBot.answer_web_app_query #: telebot.TeleBot.approve_chat_join_request telebot.TeleBot.ban_chat_member #: telebot.TeleBot.ban_chat_sender_chat telebot.TeleBot.callback_query_handler -#: telebot.TeleBot.channel_post_handler +#: telebot.TeleBot.channel_post_handler telebot.TeleBot.chat_boost_handler #: telebot.TeleBot.chat_join_request_handler #: telebot.TeleBot.chat_member_handler telebot.TeleBot.chosen_inline_handler #: telebot.TeleBot.clear_reply_handlers @@ -322,15 +334,17 @@ msgstr "Данные для добавления" #: telebot.TeleBot.clear_step_handler #: telebot.TeleBot.clear_step_handler_by_chat_id telebot.TeleBot.close #: telebot.TeleBot.close_forum_topic telebot.TeleBot.copy_message -#: telebot.TeleBot.create_chat_invite_link telebot.TeleBot.create_forum_topic -#: telebot.TeleBot.create_invoice_link telebot.TeleBot.create_new_sticker_set +#: telebot.TeleBot.copy_messages telebot.TeleBot.create_chat_invite_link +#: telebot.TeleBot.create_forum_topic telebot.TeleBot.create_invoice_link +#: telebot.TeleBot.create_new_sticker_set #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic -#: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands -#: telebot.TeleBot.delete_state telebot.TeleBot.delete_sticker_from_set -#: telebot.TeleBot.delete_sticker_set telebot.TeleBot.delete_webhook -#: telebot.TeleBot.download_file telebot.TeleBot.edit_chat_invite_link -#: telebot.TeleBot.edit_forum_topic telebot.TeleBot.edit_message_caption +#: telebot.TeleBot.delete_message telebot.TeleBot.delete_messages +#: telebot.TeleBot.delete_my_commands telebot.TeleBot.delete_state +#: telebot.TeleBot.delete_sticker_from_set telebot.TeleBot.delete_sticker_set +#: telebot.TeleBot.delete_webhook telebot.TeleBot.download_file +#: telebot.TeleBot.edit_chat_invite_link telebot.TeleBot.edit_forum_topic +#: telebot.TeleBot.edit_message_caption #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text @@ -338,9 +352,9 @@ msgstr "Данные для добавления" #: telebot.TeleBot.edited_message_handler #: telebot.TeleBot.enable_save_next_step_handlers #: telebot.TeleBot.export_chat_invite_link telebot.TeleBot.forward_message -#: telebot.TeleBot.get_chat telebot.TeleBot.get_chat_administrators -#: telebot.TeleBot.get_chat_member telebot.TeleBot.get_chat_member_count -#: telebot.TeleBot.get_chat_menu_button +#: telebot.TeleBot.forward_messages telebot.TeleBot.get_chat +#: telebot.TeleBot.get_chat_administrators telebot.TeleBot.get_chat_member +#: telebot.TeleBot.get_chat_member_count telebot.TeleBot.get_chat_menu_button #: telebot.TeleBot.get_custom_emoji_stickers telebot.TeleBot.get_file #: telebot.TeleBot.get_file_url telebot.TeleBot.get_forum_topic_icon_stickers #: telebot.TeleBot.get_game_high_scores telebot.TeleBot.get_my_commands @@ -348,16 +362,19 @@ msgstr "Данные для добавления" #: telebot.TeleBot.get_my_description telebot.TeleBot.get_my_name #: telebot.TeleBot.get_my_short_description telebot.TeleBot.get_state #: telebot.TeleBot.get_sticker_set telebot.TeleBot.get_updates -#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info -#: telebot.TeleBot.infinity_polling telebot.TeleBot.inline_handler -#: telebot.TeleBot.leave_chat telebot.TeleBot.log_out -#: telebot.TeleBot.message_handler telebot.TeleBot.middleware_handler +#: telebot.TeleBot.get_user_chat_boosts telebot.TeleBot.get_user_profile_photos +#: telebot.TeleBot.get_webhook_info telebot.TeleBot.infinity_polling +#: telebot.TeleBot.inline_handler telebot.TeleBot.leave_chat +#: telebot.TeleBot.log_out telebot.TeleBot.message_handler +#: telebot.TeleBot.message_reaction_count_handler +#: telebot.TeleBot.message_reaction_handler telebot.TeleBot.middleware_handler #: telebot.TeleBot.my_chat_member_handler telebot.TeleBot.pin_chat_message #: telebot.TeleBot.poll_answer_handler telebot.TeleBot.poll_handler #: telebot.TeleBot.polling telebot.TeleBot.pre_checkout_query_handler #: telebot.TeleBot.promote_chat_member #: telebot.TeleBot.register_callback_query_handler #: telebot.TeleBot.register_channel_post_handler +#: telebot.TeleBot.register_chat_boost_handler #: telebot.TeleBot.register_chat_join_request_handler #: telebot.TeleBot.register_chosen_inline_handler #: telebot.TeleBot.register_edited_channel_post_handler @@ -366,6 +383,8 @@ msgstr "Данные для добавления" #: telebot.TeleBot.register_for_reply_by_message_id #: telebot.TeleBot.register_inline_handler #: telebot.TeleBot.register_message_handler +#: telebot.TeleBot.register_message_reaction_count_handler +#: telebot.TeleBot.register_message_reaction_handler #: telebot.TeleBot.register_middleware_handler #: telebot.TeleBot.register_my_chat_member_handler #: telebot.TeleBot.register_next_step_handler @@ -373,25 +392,28 @@ msgstr "Данные для добавления" #: telebot.TeleBot.register_poll_answer_handler #: telebot.TeleBot.register_poll_handler #: telebot.TeleBot.register_pre_checkout_query_handler +#: telebot.TeleBot.register_removed_chat_boost_handler #: telebot.TeleBot.register_shipping_query_handler -#: telebot.TeleBot.remove_webhook telebot.TeleBot.reopen_forum_topic -#: telebot.TeleBot.reply_to telebot.TeleBot.reset_data -#: telebot.TeleBot.restrict_chat_member telebot.TeleBot.retrieve_data -#: telebot.TeleBot.revoke_chat_invite_link telebot.TeleBot.send_animation -#: telebot.TeleBot.send_audio telebot.TeleBot.send_chat_action -#: telebot.TeleBot.send_contact telebot.TeleBot.send_dice -#: telebot.TeleBot.send_document telebot.TeleBot.send_game -#: telebot.TeleBot.send_invoice telebot.TeleBot.send_location -#: telebot.TeleBot.send_media_group telebot.TeleBot.send_message -#: telebot.TeleBot.send_photo telebot.TeleBot.send_poll -#: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue -#: telebot.TeleBot.send_video telebot.TeleBot.send_voice +#: telebot.TeleBot.remove_webhook telebot.TeleBot.removed_chat_boost_handler +#: telebot.TeleBot.reopen_forum_topic telebot.TeleBot.reply_to +#: telebot.TeleBot.reset_data telebot.TeleBot.restrict_chat_member +#: telebot.TeleBot.retrieve_data telebot.TeleBot.revoke_chat_invite_link +#: telebot.TeleBot.send_animation telebot.TeleBot.send_audio +#: telebot.TeleBot.send_chat_action telebot.TeleBot.send_contact +#: telebot.TeleBot.send_dice telebot.TeleBot.send_document +#: telebot.TeleBot.send_game telebot.TeleBot.send_invoice +#: telebot.TeleBot.send_location telebot.TeleBot.send_media_group +#: telebot.TeleBot.send_message telebot.TeleBot.send_photo +#: telebot.TeleBot.send_poll telebot.TeleBot.send_sticker +#: telebot.TeleBot.send_venue telebot.TeleBot.send_video +#: telebot.TeleBot.send_video_note telebot.TeleBot.send_voice #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo #: telebot.TeleBot.set_chat_sticker_set telebot.TeleBot.set_chat_title #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail -#: telebot.TeleBot.set_game_score telebot.TeleBot.set_my_commands +#: telebot.TeleBot.set_game_score telebot.TeleBot.set_message_reaction +#: telebot.TeleBot.set_my_commands #: telebot.TeleBot.set_my_default_administrator_rights #: telebot.TeleBot.set_my_description telebot.TeleBot.set_my_name #: telebot.TeleBot.set_my_short_description telebot.TeleBot.set_state @@ -405,6 +427,7 @@ msgstr "Данные для добавления" #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat #: telebot.TeleBot.unpin_all_chat_messages #: telebot.TeleBot.unpin_all_forum_topic_messages +#: telebot.TeleBot.unpin_all_general_forum_topic_messages #: telebot.TeleBot.unpin_chat_message telebot.TeleBot.upload_sticker_file #: telebot.TeleBot.user telebot.custom_filters.TextFilter #: telebot.ext.sync.webhooks.SyncWebhookListener.run_app @@ -412,7 +435,7 @@ msgid "Returns" msgstr "" #: of telebot.TeleBot.add_data:10 telebot.TeleBot.callback_query_handler:9 -#: telebot.TeleBot.channel_post_handler:18 +#: telebot.TeleBot.channel_post_handler:18 telebot.TeleBot.chat_boost_handler:8 #: telebot.TeleBot.chat_join_request_handler:10 #: telebot.TeleBot.chat_member_handler:11 #: telebot.TeleBot.chosen_inline_handler:10 @@ -427,21 +450,26 @@ msgstr "" #: telebot.TeleBot.pre_checkout_query_handler:9 #: telebot.TeleBot.register_callback_query_handler:14 #: telebot.TeleBot.register_channel_post_handler:23 +#: telebot.TeleBot.register_chat_boost_handler:13 #: telebot.TeleBot.register_chat_join_request_handler:14 #: telebot.TeleBot.register_chosen_inline_handler:14 #: telebot.TeleBot.register_edited_message_handler:26 #: telebot.TeleBot.register_for_reply:15 #: telebot.TeleBot.register_for_reply_by_message_id:15 #: telebot.TeleBot.register_message_handler:26 +#: telebot.TeleBot.register_message_reaction_count_handler:14 +#: telebot.TeleBot.register_message_reaction_handler:14 #: telebot.TeleBot.register_middleware_handler:18 #: telebot.TeleBot.register_my_chat_member_handler:14 #: telebot.TeleBot.register_next_step_handler:15 #: telebot.TeleBot.register_next_step_handler_by_chat_id:15 #: telebot.TeleBot.register_poll_answer_handler:14 #: telebot.TeleBot.register_poll_handler:14 +#: telebot.TeleBot.register_removed_chat_boost_handler:13 #: telebot.TeleBot.register_shipping_query_handler:14 -#: telebot.TeleBot.reset_data:9 telebot.TeleBot.set_state:18 -#: telebot.TeleBot.setup_middleware:5 telebot.TeleBot.shipping_query_handler:9 +#: telebot.TeleBot.removed_chat_boost_handler:8 telebot.TeleBot.reset_data:9 +#: telebot.TeleBot.set_state:18 telebot.TeleBot.setup_middleware:5 +#: telebot.TeleBot.shipping_query_handler:9 #: telebot.custom_filters.TextFilter:22 #: telebot.ext.sync.webhooks.SyncWebhookListener.run_app:4 msgid "None" @@ -542,6 +570,7 @@ msgstr "" #: telebot.TeleBot.set_sticker_position_in_set:11 #: telebot.TeleBot.set_sticker_set_thumbnail:15 #: telebot.TeleBot.unpin_all_forum_topic_messages:13 +#: telebot.TeleBot.unpin_all_general_forum_topic_messages:11 msgid "On success, True is returned." msgstr "В случае успеха возвращается True." @@ -551,9 +580,9 @@ msgstr "В случае успеха возвращается True." #: telebot.TeleBot.answer_shipping_query telebot.TeleBot.answer_web_app_query #: telebot.TeleBot.approve_chat_join_request telebot.TeleBot.ban_chat_member #: telebot.TeleBot.ban_chat_sender_chat telebot.TeleBot.close_forum_topic -#: telebot.TeleBot.copy_message telebot.TeleBot.create_chat_invite_link -#: telebot.TeleBot.create_forum_topic telebot.TeleBot.create_invoice_link -#: telebot.TeleBot.create_new_sticker_set +#: telebot.TeleBot.copy_message telebot.TeleBot.copy_messages +#: telebot.TeleBot.create_chat_invite_link telebot.TeleBot.create_forum_topic +#: telebot.TeleBot.create_invoice_link telebot.TeleBot.create_new_sticker_set #: telebot.TeleBot.decline_chat_join_request telebot.TeleBot.delete_chat_photo #: telebot.TeleBot.delete_chat_sticker_set telebot.TeleBot.delete_forum_topic #: telebot.TeleBot.delete_message telebot.TeleBot.delete_my_commands @@ -564,28 +593,30 @@ msgstr "В случае успеха возвращается True." #: telebot.TeleBot.edit_message_live_location #: telebot.TeleBot.edit_message_media telebot.TeleBot.edit_message_reply_markup #: telebot.TeleBot.edit_message_text telebot.TeleBot.export_chat_invite_link -#: telebot.TeleBot.forward_message telebot.TeleBot.get_chat -#: telebot.TeleBot.get_chat_administrators telebot.TeleBot.get_chat_member -#: telebot.TeleBot.get_chat_member_count telebot.TeleBot.get_chat_menu_button +#: telebot.TeleBot.forward_message telebot.TeleBot.forward_messages +#: telebot.TeleBot.get_chat telebot.TeleBot.get_chat_administrators +#: telebot.TeleBot.get_chat_member telebot.TeleBot.get_chat_member_count +#: telebot.TeleBot.get_chat_menu_button #: telebot.TeleBot.get_custom_emoji_stickers telebot.TeleBot.get_file_url #: telebot.TeleBot.get_forum_topic_icon_stickers #: telebot.TeleBot.get_game_high_scores telebot.TeleBot.get_my_commands #: telebot.TeleBot.get_my_default_administrator_rights #: telebot.TeleBot.get_state telebot.TeleBot.get_sticker_set -#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_profile_photos -#: telebot.TeleBot.get_webhook_info telebot.TeleBot.log_out -#: telebot.TeleBot.pin_chat_message telebot.TeleBot.promote_chat_member -#: telebot.TeleBot.remove_webhook telebot.TeleBot.reopen_forum_topic -#: telebot.TeleBot.reply_to telebot.TeleBot.restrict_chat_member -#: telebot.TeleBot.retrieve_data telebot.TeleBot.revoke_chat_invite_link -#: telebot.TeleBot.send_animation telebot.TeleBot.send_audio -#: telebot.TeleBot.send_chat_action telebot.TeleBot.send_contact -#: telebot.TeleBot.send_dice telebot.TeleBot.send_document -#: telebot.TeleBot.send_game telebot.TeleBot.send_invoice -#: telebot.TeleBot.send_location telebot.TeleBot.send_media_group -#: telebot.TeleBot.send_message telebot.TeleBot.send_photo -#: telebot.TeleBot.send_poll telebot.TeleBot.send_sticker -#: telebot.TeleBot.send_venue telebot.TeleBot.send_video +#: telebot.TeleBot.get_updates telebot.TeleBot.get_user_chat_boosts +#: telebot.TeleBot.get_user_profile_photos telebot.TeleBot.get_webhook_info +#: telebot.TeleBot.log_out telebot.TeleBot.pin_chat_message +#: telebot.TeleBot.promote_chat_member telebot.TeleBot.remove_webhook +#: telebot.TeleBot.reopen_forum_topic telebot.TeleBot.reply_to +#: telebot.TeleBot.restrict_chat_member telebot.TeleBot.retrieve_data +#: telebot.TeleBot.revoke_chat_invite_link telebot.TeleBot.send_animation +#: telebot.TeleBot.send_audio telebot.TeleBot.send_chat_action +#: telebot.TeleBot.send_contact telebot.TeleBot.send_dice +#: telebot.TeleBot.send_document telebot.TeleBot.send_game +#: telebot.TeleBot.send_invoice telebot.TeleBot.send_location +#: telebot.TeleBot.send_media_group telebot.TeleBot.send_message +#: telebot.TeleBot.send_photo telebot.TeleBot.send_poll +#: telebot.TeleBot.send_sticker telebot.TeleBot.send_venue +#: telebot.TeleBot.send_video telebot.TeleBot.send_video_note #: telebot.TeleBot.set_chat_administrator_custom_title #: telebot.TeleBot.set_chat_description telebot.TeleBot.set_chat_menu_button #: telebot.TeleBot.set_chat_permissions telebot.TeleBot.set_chat_photo @@ -602,6 +633,7 @@ msgstr "В случае успеха возвращается True." #: telebot.TeleBot.unban_chat_member telebot.TeleBot.unban_chat_sender_chat #: telebot.TeleBot.unpin_all_chat_messages #: telebot.TeleBot.unpin_all_forum_topic_messages +#: telebot.TeleBot.unpin_all_general_forum_topic_messages #: telebot.TeleBot.unpin_chat_message telebot.TeleBot.upload_sticker_file #: telebot.TeleBot.user msgid "Return type" @@ -625,18 +657,16 @@ msgstr "" #: telebot.TeleBot.delete_sticker_set:7 telebot.TeleBot.delete_webhook:13 #: telebot.TeleBot.edit_forum_topic:23 telebot.TeleBot.leave_chat:8 #: telebot.TeleBot.log_out:11 telebot.TeleBot.pin_chat_message:19 -#: telebot.TeleBot.promote_chat_member:61 telebot.TeleBot.remove_webhook:4 +#: telebot.TeleBot.promote_chat_member:70 telebot.TeleBot.remove_webhook:4 #: telebot.TeleBot.reopen_forum_topic:14 #: telebot.TeleBot.restrict_chat_member:61 telebot.TeleBot.send_chat_action:26 -#: telebot.TeleBot.send_video_note:28 telebot.TeleBot.send_video_note:40 -#: telebot.TeleBot.send_video_note:43 #: telebot.TeleBot.set_chat_administrator_custom_title:18 #: telebot.TeleBot.set_chat_description:14 #: telebot.TeleBot.set_chat_menu_button:15 #: telebot.TeleBot.set_chat_permissions:21 telebot.TeleBot.set_chat_photo:16 #: telebot.TeleBot.set_chat_title:17 #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:11 -#: telebot.TeleBot.set_my_commands:18 +#: telebot.TeleBot.set_message_reaction:18 telebot.TeleBot.set_my_commands:18 #: telebot.TeleBot.set_my_default_administrator_rights:18 #: telebot.TeleBot.set_sticker_emoji_list:11 #: telebot.TeleBot.set_sticker_keywords:12 @@ -648,6 +678,7 @@ msgstr "" #: telebot.TeleBot.unban_chat_sender_chat:15 #: telebot.TeleBot.unpin_all_chat_messages:12 #: telebot.TeleBot.unpin_all_forum_topic_messages:14 +#: telebot.TeleBot.unpin_all_general_forum_topic_messages:12 #: telebot.TeleBot.unpin_chat_message:15 msgid ":obj:`bool`" msgstr "" @@ -967,7 +998,8 @@ msgstr "" #: of telebot.TeleBot.approve_chat_join_request:11 #: telebot.TeleBot.ban_chat_member:12 #: telebot.TeleBot.decline_chat_join_request:11 -#: telebot.TeleBot.get_chat_member:8 telebot.TeleBot.get_user_profile_photos:6 +#: telebot.TeleBot.get_chat_member:8 telebot.TeleBot.get_user_chat_boosts:8 +#: telebot.TeleBot.get_user_profile_photos:6 #: telebot.TeleBot.promote_chat_member:11 #: telebot.TeleBot.restrict_chat_member:14 #: telebot.TeleBot.set_chat_administrator_custom_title:10 @@ -980,7 +1012,7 @@ msgstr "Уникальный id сделавшего запрос пользов #: telebot.TeleBot.decline_chat_join_request:14 #: telebot.TeleBot.delete_chat_photo:12 telebot.TeleBot.delete_my_commands:16 #: telebot.TeleBot.log_out:10 telebot.TeleBot.pin_chat_message:18 -#: telebot.TeleBot.promote_chat_member:60 telebot.TeleBot.remove_webhook:3 +#: telebot.TeleBot.promote_chat_member:69 telebot.TeleBot.remove_webhook:3 #: telebot.TeleBot.set_chat_administrator_custom_title:17 #: telebot.TeleBot.set_chat_description:13 #: telebot.TeleBot.set_chat_menu_button:14 telebot.TeleBot.set_chat_photo:15 @@ -1041,8 +1073,8 @@ msgstr "" #: of telebot.TeleBot.ban_chat_member:24 #: telebot.TeleBot.delete_chat_sticker_set:10 telebot.TeleBot.delete_message:22 -#: telebot.TeleBot.delete_sticker_set:6 telebot.TeleBot.delete_webhook:12 -#: telebot.TeleBot.send_chat_action:25 +#: telebot.TeleBot.delete_messages:14 telebot.TeleBot.delete_sticker_set:6 +#: telebot.TeleBot.delete_webhook:12 telebot.TeleBot.send_chat_action:25 #: telebot.TeleBot.set_custom_emoji_sticker_set_thumbnail:10 #: telebot.TeleBot.set_sticker_emoji_list:10 #: telebot.TeleBot.set_sticker_mask_position:11 @@ -1075,11 +1107,13 @@ msgstr "" #: of telebot.TeleBot.ban_chat_sender_chat:10 #: telebot.TeleBot.close_forum_topic:7 #: telebot.TeleBot.close_general_forum_topic:7 telebot.TeleBot.copy_message:5 -#: telebot.TeleBot.create_forum_topic:7 telebot.TeleBot.delete_forum_topic:7 -#: telebot.TeleBot.delete_message:13 telebot.TeleBot.edit_forum_topic:7 +#: telebot.TeleBot.copy_messages:3 telebot.TeleBot.create_forum_topic:7 +#: telebot.TeleBot.delete_forum_topic:7 telebot.TeleBot.delete_message:13 +#: telebot.TeleBot.delete_messages:8 telebot.TeleBot.edit_forum_topic:7 #: telebot.TeleBot.edit_general_forum_topic:7 #: telebot.TeleBot.edit_message_live_location:13 -#: telebot.TeleBot.forward_message:8 telebot.TeleBot.hide_general_forum_topic:7 +#: telebot.TeleBot.forward_message:8 telebot.TeleBot.forward_messages:3 +#: telebot.TeleBot.hide_general_forum_topic:7 #: telebot.TeleBot.pin_chat_message:7 telebot.TeleBot.reopen_forum_topic:7 #: telebot.TeleBot.reopen_general_forum_topic:7 #: telebot.TeleBot.send_animation:6 telebot.TeleBot.send_audio:9 @@ -1113,17 +1147,20 @@ msgstr "" "декорируемую функцию объект :class:`telebot.types.CallbackQuery`." #: of telebot.TeleBot.callback_query_handler:4 -#: telebot.TeleBot.channel_post_handler:10 +#: telebot.TeleBot.channel_post_handler:10 telebot.TeleBot.chat_boost_handler:4 #: telebot.TeleBot.chat_join_request_handler:5 #: telebot.TeleBot.chat_member_handler:6 #: telebot.TeleBot.chosen_inline_handler:5 #: telebot.TeleBot.edited_channel_post_handler:10 #: telebot.TeleBot.edited_message_handler:10 telebot.TeleBot.inline_handler:4 +#: telebot.TeleBot.message_reaction_count_handler:4 +#: telebot.TeleBot.message_reaction_handler:4 #: telebot.TeleBot.my_chat_member_handler:5 #: telebot.TeleBot.poll_answer_handler:5 telebot.TeleBot.poll_handler:4 #: telebot.TeleBot.pre_checkout_query_handler:4 #: telebot.TeleBot.register_callback_query_handler:6 #: telebot.TeleBot.register_channel_post_handler:15 +#: telebot.TeleBot.register_chat_boost_handler:6 #: telebot.TeleBot.register_chat_join_request_handler:6 #: telebot.TeleBot.register_chat_member_handler:6 #: telebot.TeleBot.register_chosen_inline_handler:6 @@ -1131,27 +1168,35 @@ msgstr "" #: telebot.TeleBot.register_edited_message_handler:15 #: telebot.TeleBot.register_inline_handler:6 #: telebot.TeleBot.register_message_handler:15 +#: telebot.TeleBot.register_message_reaction_count_handler:6 +#: telebot.TeleBot.register_message_reaction_handler:6 #: telebot.TeleBot.register_my_chat_member_handler:6 #: telebot.TeleBot.register_poll_answer_handler:6 #: telebot.TeleBot.register_poll_handler:6 #: telebot.TeleBot.register_pre_checkout_query_handler:6 +#: telebot.TeleBot.register_removed_chat_boost_handler:6 #: telebot.TeleBot.register_shipping_query_handler:6 +#: telebot.TeleBot.removed_chat_boost_handler:4 #: telebot.TeleBot.shipping_query_handler:4 msgid "Function executed as a filter" msgstr "Функция, используемая в качестве фильтра" #: of telebot.TeleBot.callback_query_handler:7 -#: telebot.TeleBot.channel_post_handler:16 +#: telebot.TeleBot.channel_post_handler:16 telebot.TeleBot.chat_boost_handler:7 #: telebot.TeleBot.chat_join_request_handler:8 #: telebot.TeleBot.chat_member_handler:9 #: telebot.TeleBot.chosen_inline_handler:8 #: telebot.TeleBot.edited_channel_post_handler:16 #: telebot.TeleBot.edited_message_handler:19 telebot.TeleBot.inline_handler:7 -#: telebot.TeleBot.message_handler:50 telebot.TeleBot.my_chat_member_handler:8 +#: telebot.TeleBot.message_handler:50 +#: telebot.TeleBot.message_reaction_count_handler:7 +#: telebot.TeleBot.message_reaction_handler:7 +#: telebot.TeleBot.my_chat_member_handler:8 #: telebot.TeleBot.poll_answer_handler:8 telebot.TeleBot.poll_handler:7 #: telebot.TeleBot.pre_checkout_query_handler:7 #: telebot.TeleBot.register_callback_query_handler:12 #: telebot.TeleBot.register_channel_post_handler:21 +#: telebot.TeleBot.register_chat_boost_handler:11 #: telebot.TeleBot.register_chat_join_request_handler:12 #: telebot.TeleBot.register_chat_member_handler:12 #: telebot.TeleBot.register_chosen_inline_handler:12 @@ -1159,11 +1204,15 @@ msgstr "Функция, используемая в качестве фильт #: telebot.TeleBot.register_edited_message_handler:24 #: telebot.TeleBot.register_inline_handler:12 #: telebot.TeleBot.register_message_handler:24 +#: telebot.TeleBot.register_message_reaction_count_handler:12 +#: telebot.TeleBot.register_message_reaction_handler:12 #: telebot.TeleBot.register_my_chat_member_handler:12 #: telebot.TeleBot.register_poll_answer_handler:12 #: telebot.TeleBot.register_poll_handler:12 #: telebot.TeleBot.register_pre_checkout_query_handler:11 +#: telebot.TeleBot.register_removed_chat_boost_handler:11 #: telebot.TeleBot.register_shipping_query_handler:12 +#: telebot.TeleBot.removed_chat_boost_handler:7 #: telebot.TeleBot.shipping_query_handler:7 msgid "Optional keyword arguments(custom filters)" msgstr "Необязательные именованные аргументы(кастомные фильтры)" @@ -1200,6 +1249,15 @@ msgstr "Необязательное регулярное выражение." msgid "Supported message content types. Must be a list. Defaults to ['text']." msgstr "Обрабатываемые виды контента. Обязан быть списком. По умолчанию ['text']" +#: of telebot.TeleBot.chat_boost_handler:1 +#, fuzzy +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostUpdated` object." +msgstr "" +"Обрабатывает новый callback query. В качестве параметра передаёт в " +"декорируемую функцию объект :class:`telebot.types.CallbackQuery`." + #: of telebot.TeleBot.chat_join_request_handler:1 msgid "" "Handles a request to join the chat has been sent. The bot must have the " @@ -1307,6 +1365,10 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#closeforumtopic" msgstr "Документация Telegram: https://core.telegram.org/bots/api#closeforumtopic" +#: of telebot.TeleBot.close_forum_topic +msgid "aram chat_id" +msgstr "" + #: of telebot.TeleBot.close_forum_topic:10 msgid "Identifier of the topic to close" msgstr "id топика для закрытия" @@ -1328,7 +1390,7 @@ msgid "" "https://core.telegram.org/bots/api#closegeneralforumtopic" msgstr "Документация Telegram: https://core.telegram.org/bots/api#closeforumtopic" -#: of telebot.TeleBot.copy_message:1 +#: of telebot.TeleBot.copy_message:1 telebot.TeleBot.copy_messages:1 msgid "Use this method to copy messages of any kind." msgstr "Используйте этот метод для копирования любых сообщений." @@ -1336,7 +1398,8 @@ msgstr "Используйте этот метод для копирования msgid "Telegram documentation: https://core.telegram.org/bots/api#copymessage" msgstr "Документация Telegram: https://core.telegram.org/bots/api#copymessage" -#: of telebot.TeleBot.copy_message:8 telebot.TeleBot.forward_message:11 +#: of telebot.TeleBot.copy_message:8 telebot.TeleBot.copy_messages:6 +#: telebot.TeleBot.forward_message:11 telebot.TeleBot.forward_messages:6 msgid "" "Unique identifier for the chat where the original message was sent (or " "channel username in the format @channelusername)" @@ -1368,14 +1431,14 @@ msgstr "" "Список отформатированных частей новой подписи в формате JSON, можно " "использовать вместо parse_mode" -#: of telebot.TeleBot.copy_message:22 telebot.TeleBot.send_animation:45 -#: telebot.TeleBot.send_audio:39 telebot.TeleBot.send_contact:20 -#: telebot.TeleBot.send_dice:12 telebot.TeleBot.send_document:26 +#: of telebot.TeleBot.copy_message:22 telebot.TeleBot.send_animation:48 +#: telebot.TeleBot.send_audio:36 telebot.TeleBot.send_contact:20 +#: telebot.TeleBot.send_dice:12 telebot.TeleBot.send_document:23 #: telebot.TeleBot.send_game:11 telebot.TeleBot.send_invoice:67 -#: telebot.TeleBot.send_location:25 telebot.TeleBot.send_message:24 +#: telebot.TeleBot.send_location:22 telebot.TeleBot.send_message:24 #: telebot.TeleBot.send_photo:22 telebot.TeleBot.send_poll:44 #: telebot.TeleBot.send_venue:27 telebot.TeleBot.send_video:35 -#: telebot.TeleBot.send_video_note:27 telebot.TeleBot.send_voice:31 +#: telebot.TeleBot.send_video_note:24 telebot.TeleBot.send_voice:28 msgid "" "Sends the message silently. Users will receive a notification with no " "sound." @@ -1384,50 +1447,47 @@ msgstr "" "уведомление без звука." #: of telebot.TeleBot.copy_message:25 telebot.TeleBot.send_animation:34 -#: telebot.TeleBot.send_audio:57 telebot.TeleBot.send_contact:38 -#: telebot.TeleBot.send_document:50 telebot.TeleBot.send_invoice:95 +#: telebot.TeleBot.send_audio:57 telebot.TeleBot.send_contact:37 +#: telebot.TeleBot.send_dice:29 telebot.TeleBot.send_document:50 +#: telebot.TeleBot.send_game:26 telebot.TeleBot.send_invoice:95 #: telebot.TeleBot.send_location:43 telebot.TeleBot.send_media_group:15 -#: telebot.TeleBot.send_photo:25 telebot.TeleBot.send_poll:64 -#: telebot.TeleBot.send_sticker:30 telebot.TeleBot.send_venue:51 -#: telebot.TeleBot.send_video:38 telebot.TeleBot.send_video_note:42 -#: telebot.TeleBot.send_voice:43 +#: telebot.TeleBot.send_message:27 telebot.TeleBot.send_photo:25 +#: telebot.TeleBot.send_poll:64 telebot.TeleBot.send_sticker:30 +#: telebot.TeleBot.send_venue:50 telebot.TeleBot.send_video:38 +#: telebot.TeleBot.send_video_note:42 telebot.TeleBot.send_voice:43 msgid "Protects the contents of the sent message from forwarding and saving" msgstr "Запретить пересылку и сохранение содержимого сообщения" -#: of telebot.TeleBot.copy_message:28 telebot.TeleBot.send_animation:37 -#: telebot.TeleBot.send_audio:29 telebot.TeleBot.send_contact:23 -#: telebot.TeleBot.send_dice:15 telebot.TeleBot.send_document:12 -#: telebot.TeleBot.send_game:14 telebot.TeleBot.send_invoice:70 -#: telebot.TeleBot.send_location:17 telebot.TeleBot.send_media_group:18 -#: telebot.TeleBot.send_message:30 telebot.TeleBot.send_photo:28 -#: telebot.TeleBot.send_poll:47 telebot.TeleBot.send_sticker:13 -#: telebot.TeleBot.send_venue:30 telebot.TeleBot.send_video:41 -#: telebot.TeleBot.send_video_note:19 telebot.TeleBot.send_voice:20 -msgid "If the message is a reply, ID of the original message" -msgstr "Если сообщение является ответом - id сообщения, на которое дан ответ" - -#: of telebot.TeleBot.copy_message:31 telebot.TeleBot.send_animation:54 -#: telebot.TeleBot.send_audio:54 telebot.TeleBot.send_dice:26 -#: telebot.TeleBot.send_document:38 telebot.TeleBot.send_invoice:84 -#: telebot.TeleBot.send_location:40 telebot.TeleBot.send_media_group:24 -#: telebot.TeleBot.send_message:33 telebot.TeleBot.send_photo:31 -#: telebot.TeleBot.send_sticker:27 telebot.TeleBot.send_video:44 -#: telebot.TeleBot.send_video_note:39 telebot.TeleBot.send_voice:40 -msgid "" -"Pass True, if the message should be sent even if the specified replied-to" -" message is not found" -msgstr "" -"Передайте True, если сообщение нужно отправить даже в случае отсутствия " -"сообщения, на которое дан ответ" - -#: of telebot.TeleBot.copy_message:34 telebot.TeleBot.send_animation:40 -#: telebot.TeleBot.send_contact:26 telebot.TeleBot.send_dice:18 -#: telebot.TeleBot.send_document:18 telebot.TeleBot.send_game:17 -#: telebot.TeleBot.send_location:20 telebot.TeleBot.send_message:36 +#: of telebot.TeleBot.copy_message:28 telebot.TeleBot.copy_message:31 +#: telebot.TeleBot.edit_message_text:23 telebot.TeleBot.polling:44 +#: telebot.TeleBot.send_animation:37 telebot.TeleBot.send_animation:40 +#: telebot.TeleBot.send_animation:63 telebot.TeleBot.send_audio:39 +#: telebot.TeleBot.send_audio:42 telebot.TeleBot.send_audio:63 +#: telebot.TeleBot.send_contact:23 telebot.TeleBot.send_contact:26 +#: telebot.TeleBot.send_dice:20 telebot.TeleBot.send_dice:23 +#: telebot.TeleBot.send_document:26 telebot.TeleBot.send_document:29 +#: telebot.TeleBot.send_document:56 telebot.TeleBot.send_location:25 +#: telebot.TeleBot.send_location:28 telebot.TeleBot.send_media_group:18 +#: telebot.TeleBot.send_media_group:21 telebot.TeleBot.send_message:21 +#: telebot.TeleBot.send_message:30 telebot.TeleBot.send_message:33 +#: telebot.TeleBot.send_photo:28 telebot.TeleBot.send_photo:31 +#: telebot.TeleBot.send_sticker:21 telebot.TeleBot.send_sticker:24 +#: telebot.TeleBot.send_venue:30 telebot.TeleBot.send_venue:33 +#: telebot.TeleBot.send_video:41 telebot.TeleBot.send_video:44 +#: telebot.TeleBot.send_video:64 telebot.TeleBot.send_video_note:27 +#: telebot.TeleBot.send_video_note:30 telebot.TeleBot.send_video_note:48 +#: telebot.TeleBot.send_voice:31 telebot.TeleBot.send_voice:34 +msgid "deprecated." +msgstr "" + +#: of telebot.TeleBot.copy_message:34 telebot.TeleBot.send_animation:43 +#: telebot.TeleBot.send_contact:29 telebot.TeleBot.send_dice:15 +#: telebot.TeleBot.send_document:15 telebot.TeleBot.send_game:20 +#: telebot.TeleBot.send_location:17 telebot.TeleBot.send_message:36 #: telebot.TeleBot.send_photo:34 telebot.TeleBot.send_poll:53 -#: telebot.TeleBot.send_sticker:16 telebot.TeleBot.send_venue:33 -#: telebot.TeleBot.send_video:47 telebot.TeleBot.send_video_note:22 -#: telebot.TeleBot.send_voice:23 +#: telebot.TeleBot.send_sticker:13 telebot.TeleBot.send_venue:36 +#: telebot.TeleBot.send_video:47 telebot.TeleBot.send_video_note:19 +#: telebot.TeleBot.send_voice:20 msgid "" "Additional interface options. A JSON-serialized object for an inline " "keyboard, custom reply keyboard, instructions to remove reply keyboard or" @@ -1439,14 +1499,14 @@ msgstr "" #: of telebot.TeleBot.copy_message:39 telebot.TeleBot.delete_message:19 #: telebot.TeleBot.edit_message_live_location:23 -#: telebot.TeleBot.forward_message:20 telebot.TeleBot.send_animation:48 -#: telebot.TeleBot.send_audio:42 telebot.TeleBot.send_chat_action:19 -#: telebot.TeleBot.send_contact:31 telebot.TeleBot.send_dice:23 -#: telebot.TeleBot.send_document:29 telebot.TeleBot.send_location:28 -#: telebot.TeleBot.send_media_group:21 telebot.TeleBot.send_message:40 -#: telebot.TeleBot.send_photo:39 telebot.TeleBot.send_sticker:24 -#: telebot.TeleBot.send_venue:38 telebot.TeleBot.send_video:52 -#: telebot.TeleBot.send_video_note:30 telebot.TeleBot.send_voice:34 +#: telebot.TeleBot.forward_message:20 telebot.TeleBot.send_animation:51 +#: telebot.TeleBot.send_audio:45 telebot.TeleBot.send_chat_action:19 +#: telebot.TeleBot.send_contact:34 telebot.TeleBot.send_dice:26 +#: telebot.TeleBot.send_document:32 telebot.TeleBot.send_location:31 +#: telebot.TeleBot.send_media_group:24 telebot.TeleBot.send_message:40 +#: telebot.TeleBot.send_photo:39 telebot.TeleBot.send_sticker:27 +#: telebot.TeleBot.send_venue:41 telebot.TeleBot.send_video:52 +#: telebot.TeleBot.send_video_note:33 telebot.TeleBot.send_voice:37 #: telebot.TeleBot.stop_message_live_location:19 msgid "Timeout in seconds for the request." msgstr "Таймаут запроса в секундах." @@ -1458,27 +1518,58 @@ msgstr "Таймаут запроса в секундах." msgid "Identifier of a message thread, in which the message will be sent" msgstr "id топика, в который нужно отправить сообщение" -#: of telebot.TeleBot.copy_message:45 telebot.TeleBot.forward_message:26 -#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:66 -#: telebot.TeleBot.send_audio:66 telebot.TeleBot.send_contact:44 -#: telebot.TeleBot.send_dice:35 telebot.TeleBot.send_document:59 -#: telebot.TeleBot.send_game:32 telebot.TeleBot.send_invoice:101 -#: telebot.TeleBot.send_location:49 telebot.TeleBot.send_message:46 -#: telebot.TeleBot.send_photo:48 telebot.TeleBot.send_poll:70 -#: telebot.TeleBot.send_sticker:42 telebot.TeleBot.send_venue:57 -#: telebot.TeleBot.send_video:67 telebot.TeleBot.send_voice:49 -msgid "On success, the sent Message is returned." +#: of telebot.TeleBot.copy_message:45 telebot.TeleBot.send_dice:35 +#: telebot.TeleBot.send_photo:48 +msgid "Additional parameters for replies to messages" +msgstr "" + +#: of telebot.TeleBot.copy_message:48 +#, fuzzy +msgid "On success, the MessageId of the sent message is returned." msgstr "В случае успеха возвращает отправленное сообщение (Message)." -#: of telebot.TeleBot.copy_message:46 telebot.TeleBot.forward_message:27 -#: telebot.TeleBot.reply_to:12 telebot.TeleBot.send_animation:67 -#: telebot.TeleBot.send_audio:67 telebot.TeleBot.send_contact:45 -#: telebot.TeleBot.send_dice:36 telebot.TeleBot.send_document:60 -#: telebot.TeleBot.send_location:50 telebot.TeleBot.send_message:47 -#: telebot.TeleBot.send_photo:49 telebot.TeleBot.send_sticker:43 -#: telebot.TeleBot.send_venue:58 telebot.TeleBot.send_video:68 -msgid ":class:`telebot.types.Message`" +#: of telebot.TeleBot.copy_message:49 telebot.TeleBot.forward_messages:22 +#, fuzzy +msgid ":class:`telebot.types.MessageID`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + +#: of telebot.TeleBot.copy_messages:9 telebot.TeleBot.forward_messages:9 +#, fuzzy +msgid "Message identifiers in the chat specified in from_chat_id" +msgstr "id сообщения в чате, заданном в from_chat_id" + +#: of telebot.TeleBot.copy_messages:12 telebot.TeleBot.forward_message:5 +#: telebot.TeleBot.forward_messages:12 +msgid "" +"Sends the message silently. Users will receive a notification with no " +"sound" msgstr "" +"Отправить сообщение, при получении которого пользователи получат " +"уведомление без звука" + +#: of telebot.TeleBot.copy_messages:15 telebot.TeleBot.forward_messages:15 +#, fuzzy +msgid "Identifier of a message thread, in which the messages will be sent" +msgstr "id топика, в который нужно отправить сообщение" + +#: of telebot.TeleBot.copy_messages:18 telebot.TeleBot.forward_message:17 +#: telebot.TeleBot.forward_messages:18 +msgid "Protects the contents of the forwarded message from forwarding and saving" +msgstr "Запретить пересылку и сохранение содержимого пересланного сообщения" + +#: of telebot.TeleBot.copy_messages:21 +msgid "Pass True to copy the messages without their captions" +msgstr "" + +#: of telebot.TeleBot.copy_messages:24 +#, fuzzy +msgid "On success, an array of MessageId of the sent messages is returned." +msgstr "В случае успеха возвращает отправленное сообщение (Message)." + +#: of telebot.TeleBot.copy_messages:25 +#, fuzzy +msgid ":obj:`list` of :class:`telebot.types.MessageID`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" #: of telebot.TeleBot.create_chat_invite_link:1 msgid "" @@ -1662,7 +1753,7 @@ msgstr "" " должны быть больше нуля, перечисленные в порядке строгого возрастания и " "не превышать max_tip_amount." -#: of telebot.TeleBot.create_invoice_link:36 telebot.TeleBot.send_invoice:77 +#: of telebot.TeleBot.create_invoice_link:36 telebot.TeleBot.send_invoice:80 msgid "" "A JSON-serialized data about the invoice, which will be shared with the " "payment provider. A detailed description of required fields should be " @@ -1936,6 +2027,24 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#de msgid "Identifier of the message to delete" msgstr "id сообщения, которое нужно удалить" +#: of telebot.TeleBot.delete_messages:1 +msgid "" +"Use this method to delete multiple messages in a chat. The number of " +"messages to be deleted must not exceed 100. If the chat is a private " +"chat, the user must be an administrator of the chat for this to work and " +"must have the appropriate admin rights. Returns True on success." +msgstr "" + +#: of telebot.TeleBot.delete_messages:6 +#, fuzzy +msgid "Telegram documentation: https://core.telegram.org/bots/api#deletemessages" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#deletemessage" + +#: of telebot.TeleBot.delete_messages:11 +#, fuzzy +msgid "Identifiers of the messages to be deleted" +msgstr "id сообщения, которое нужно удалить" + #: of telebot.TeleBot.delete_my_commands:1 msgid "" "Use this method to delete the list of the bot's commands for the given " @@ -2213,7 +2322,7 @@ msgstr "JSON-сериализованный объект inline клавиату #: of telebot.TeleBot.edit_message_caption:26 #: telebot.TeleBot.edit_message_media:22 #: telebot.TeleBot.edit_message_reply_markup:17 -#: telebot.TeleBot.edit_message_text:29 +#: telebot.TeleBot.edit_message_text:32 msgid "" "On success, if edited message is sent by the bot, the edited Message is " "returned, otherwise True is returned." @@ -2283,7 +2392,7 @@ msgid "" msgstr "Обязательный, если не указаны chat_id и message_id. id inline сообщения" #: of telebot.TeleBot.edit_message_live_location:29 -#: telebot.TeleBot.send_location:31 +#: telebot.TeleBot.send_location:34 msgid "The radius of uncertainty for the location, measured in meters; 0-1500" msgstr "Радиус погрешности местоположения, измеряется в метрах; 0-1500" @@ -2363,7 +2472,7 @@ msgstr "Обязательный, если не указан inline_message_id. #: of telebot.TeleBot.edit_message_media:23 #: telebot.TeleBot.edit_message_reply_markup:18 -#: telebot.TeleBot.edit_message_text:30 telebot.TeleBot.set_game_score:27 +#: telebot.TeleBot.edit_message_text:33 telebot.TeleBot.set_game_score:27 msgid ":obj:`types.Message` or :obj:`bool`" msgstr "" @@ -2403,9 +2512,11 @@ msgstr "" "Список отформатированных частей в тексте сообщения, можно использовать " "вместо parse_mode" -#: of telebot.TeleBot.edit_message_text:23 telebot.TeleBot.send_message:21 -msgid "Disables link previews for links in this message" -msgstr "Отключает превью ссылок в сообщении" +#: of telebot.TeleBot.edit_message_text:29 +msgid "" +"A JSON-serialized object for options used to automatically generate " +"previews for links." +msgstr "" #: of telebot.TeleBot.edited_channel_post_handler:1 msgid "" @@ -2507,7 +2618,7 @@ msgstr "" msgid "exported invite link as String on success." msgstr "новая ссылка-приглашение (String) в случае успеха." -#: of telebot.TeleBot.forward_message:1 +#: of telebot.TeleBot.forward_message:1 telebot.TeleBot.forward_messages:1 msgid "Use this method to forward messages of any kind." msgstr "Используйте этот метод, чтобы переслать любое сообщение." @@ -2515,17 +2626,28 @@ msgstr "Используйте этот метод, чтобы переслат msgid "Telegram documentation: https://core.telegram.org/bots/api#forwardmessage" msgstr "Документация Telegram: https://core.telegram.org/bots/api#forwardmessage" -#: of telebot.TeleBot.forward_message:5 -msgid "" -"Sends the message silently. Users will receive a notification with no " -"sound" -msgstr "" -"Отправить сообщение, при получении которого пользователи получат " -"уведомление без звука" +#: of telebot.TeleBot.forward_message:26 telebot.TeleBot.forward_messages:21 +#: telebot.TeleBot.reply_to:11 telebot.TeleBot.send_animation:69 +#: telebot.TeleBot.send_audio:69 telebot.TeleBot.send_contact:46 +#: telebot.TeleBot.send_dice:38 telebot.TeleBot.send_document:62 +#: telebot.TeleBot.send_game:35 telebot.TeleBot.send_invoice:104 +#: telebot.TeleBot.send_location:52 telebot.TeleBot.send_message:52 +#: telebot.TeleBot.send_photo:51 telebot.TeleBot.send_poll:73 +#: telebot.TeleBot.send_sticker:45 telebot.TeleBot.send_venue:59 +#: telebot.TeleBot.send_video:70 telebot.TeleBot.send_video_note:54 +#: telebot.TeleBot.send_voice:52 +msgid "On success, the sent Message is returned." +msgstr "В случае успеха возвращает отправленное сообщение (Message)." -#: of telebot.TeleBot.forward_message:17 -msgid "Protects the contents of the forwarded message from forwarding and saving" -msgstr "Запретить пересылку и сохранение содержимого пересланного сообщения" +#: of telebot.TeleBot.forward_message:27 telebot.TeleBot.reply_to:12 +#: telebot.TeleBot.send_animation:70 telebot.TeleBot.send_audio:70 +#: telebot.TeleBot.send_contact:47 telebot.TeleBot.send_dice:39 +#: telebot.TeleBot.send_document:63 telebot.TeleBot.send_location:53 +#: telebot.TeleBot.send_message:53 telebot.TeleBot.send_photo:52 +#: telebot.TeleBot.send_sticker:46 telebot.TeleBot.send_venue:60 +#: telebot.TeleBot.send_video:71 telebot.TeleBot.send_video_note:55 +msgid ":class:`telebot.types.Message`" +msgstr "" #: of telebot.TeleBot.get_chat:1 msgid "" @@ -2544,6 +2666,7 @@ msgstr "Документация Telegram: https://core.telegram.org/bots/api#ge #: of telebot.TeleBot.get_chat:6 telebot.TeleBot.get_chat_administrators:7 #: telebot.TeleBot.get_chat_member_count:5 telebot.TeleBot.leave_chat:5 +#: telebot.TeleBot.set_message_reaction:5 msgid "" "Unique identifier for the target chat or username of the target " "supergroup or channel (in the format @channelusername)" @@ -2622,9 +2745,6 @@ msgid "Number of members in the chat." msgstr "Количество участников чата." #: of telebot.TeleBot.get_chat_member_count:9 -#: telebot.TeleBot.send_video_note:14 telebot.TeleBot.send_video_note:17 -#: telebot.TeleBot.send_video_note:20 telebot.TeleBot.send_video_note:31 -#: telebot.TeleBot.send_video_note:46 msgid ":obj:`int`" msgstr "" @@ -3022,6 +3142,41 @@ msgstr "Возвращается массив объектов Update." msgid ":obj:`list` of :class:`telebot.types.Update`" msgstr "" +#: of telebot.TeleBot.get_user_chat_boosts:1 +#, fuzzy +msgid "" +"Use this method to get the list of boosts added to a chat by a user. " +"Requires administrator rights in the chat. Returns a UserChatBoosts " +"object." +msgstr "" +"Используйте этот метод, чтобы получить текущие права администратора для " +"бота по умолчанию. Возвращает объект ChatAdministratorRights в случае " +"успеха." + +#: of telebot.TeleBot.get_user_chat_boosts:3 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#getuserchatboosts" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#getchat" + +#: of telebot.TeleBot.get_user_chat_boosts:5 +#: telebot.TeleBot.send_chat_action:10 telebot.TeleBot.send_contact:5 +#: telebot.TeleBot.send_poll:6 telebot.TeleBot.send_venue:5 +#: telebot.TeleBot.stop_poll:5 +msgid "Unique identifier for the target chat or username of the target channel" +msgstr "Уникальный id чата или username канала" + +#: of telebot.TeleBot.get_user_chat_boosts:11 +#, fuzzy +msgid "On success, a UserChatBoosts object is returned." +msgstr "В случае успеха возвращается объект StickerSet." + +#: of telebot.TeleBot.get_user_chat_boosts:12 +#, fuzzy +msgid ":class:`telebot.types.UserChatBoosts`" +msgstr "Экземпляр класса :class:`telebot.types.Message`" + #: of telebot.TeleBot.get_user_profile_photos:1 msgid "" "Use this method to get a list of profile pictures for a user. Returns a " @@ -3303,6 +3458,25 @@ msgstr "" msgid "decorated function" msgstr "декорируемая функция" +#: of telebot.TeleBot.message_reaction_count_handler:1 +#, fuzzy +msgid "" +"Handles new incoming message reaction count. As a parameter to the " +"decorator function, it passes " +":class:`telebot.types.MessageReactionCountUpdated` object." +msgstr "" +"Обрабатывает новый callback query. В качестве параметра передаёт в " +"декорируемую функцию объект :class:`telebot.types.CallbackQuery`." + +#: of telebot.TeleBot.message_reaction_handler:1 +#, fuzzy +msgid "" +"Handles new incoming message reaction. As a parameter to the decorator " +"function, it passes :class:`telebot.types.MessageReactionUpdated` object." +msgstr "" +"Обрабатывает новый callback query. В качестве параметра передаёт в " +"декорируемую функцию объект :class:`telebot.types.CallbackQuery`." + #: of telebot.TeleBot.middleware_handler:1 msgid "Function-based middleware handler decorator." msgstr "Функция-декоратор для middleware хендлера." @@ -3473,12 +3647,6 @@ msgstr "" "отправленные до вызова get_updates, поэтому нежелательные апдейты могут " "быть получены в течение короткого периода времени." -#: of telebot.TeleBot.polling:44 -msgid "Deprecated, use non_stop. Old typo, kept for backward compatibility." -msgstr "" -"Устарело, используйте non_stop. Старая опечатка, оставлено для обратной " -"совместимости" - #: of telebot.TeleBot.polling:50 msgid "Path to watch for changes. Defaults to None" msgstr "Путь для мониторинга изменений. По умолчанию None" @@ -3630,12 +3798,34 @@ msgstr "" "Передайте True, если пользователю разрешено создавать, переименовывать, " "закрывать, и возобновлять топики, только для супергрупп" +#: of telebot.TeleBot.promote_chat_member:60 +#, fuzzy +msgid "Pass True if the administrator can create the channel's stories" +msgstr "" +"Передайте True, если администратор может создавать посты в канале, только" +" для каналов" + +#: of telebot.TeleBot.promote_chat_member:63 +#, fuzzy +msgid "Pass True if the administrator can edit the channel's stories" +msgstr "" +"Передайте True, если администратор может изменять сообщения других " +"пользователей, только для каналов" + +#: of telebot.TeleBot.promote_chat_member:66 +#, fuzzy +msgid "Pass True if the administrator can delete the channel's stories" +msgstr "" +"Передайте True, если администратор может создавать посты в канале, только" +" для каналов" + #: of telebot.TeleBot.register_callback_query_handler:1 msgid "Registers callback query handler." msgstr "Регистрирует хендлер callback query." #: of telebot.TeleBot.register_callback_query_handler:3 #: telebot.TeleBot.register_channel_post_handler:3 +#: telebot.TeleBot.register_chat_boost_handler:3 #: telebot.TeleBot.register_chat_join_request_handler:3 #: telebot.TeleBot.register_chat_member_handler:3 #: telebot.TeleBot.register_chosen_inline_handler:3 @@ -3643,16 +3833,20 @@ msgstr "Регистрирует хендлер callback query." #: telebot.TeleBot.register_edited_message_handler:3 #: telebot.TeleBot.register_inline_handler:3 #: telebot.TeleBot.register_message_handler:3 +#: telebot.TeleBot.register_message_reaction_count_handler:3 +#: telebot.TeleBot.register_message_reaction_handler:3 #: telebot.TeleBot.register_my_chat_member_handler:3 #: telebot.TeleBot.register_poll_answer_handler:3 #: telebot.TeleBot.register_poll_handler:3 #: telebot.TeleBot.register_pre_checkout_query_handler:3 +#: telebot.TeleBot.register_removed_chat_boost_handler:3 #: telebot.TeleBot.register_shipping_query_handler:3 msgid "function to be called" msgstr "функция-хендлер" #: of telebot.TeleBot.register_callback_query_handler:9 #: telebot.TeleBot.register_channel_post_handler:18 +#: telebot.TeleBot.register_chat_boost_handler:9 #: telebot.TeleBot.register_chat_join_request_handler:9 #: telebot.TeleBot.register_chat_member_handler:9 #: telebot.TeleBot.register_chosen_inline_handler:9 @@ -3660,10 +3854,13 @@ msgstr "функция-хендлер" #: telebot.TeleBot.register_edited_message_handler:21 #: telebot.TeleBot.register_inline_handler:9 #: telebot.TeleBot.register_message_handler:21 +#: telebot.TeleBot.register_message_reaction_count_handler:9 +#: telebot.TeleBot.register_message_reaction_handler:9 #: telebot.TeleBot.register_my_chat_member_handler:9 #: telebot.TeleBot.register_poll_answer_handler:9 #: telebot.TeleBot.register_poll_handler:9 #: telebot.TeleBot.register_pre_checkout_query_handler:8 +#: telebot.TeleBot.register_removed_chat_boost_handler:9 #: telebot.TeleBot.register_shipping_query_handler:9 msgid "" "True if you need to pass TeleBot instance to handler(useful for " @@ -3689,6 +3886,11 @@ msgstr "список команд" msgid "Regular expression" msgstr "Регулярное выражение" +#: of telebot.TeleBot.register_chat_boost_handler:1 +#, fuzzy +msgid "Registers chat boost handler." +msgstr "Регистрирует хендлер смены состояний участников чата." + #: of telebot.TeleBot.register_chat_join_request_handler:1 msgid "Registers chat join request handler." msgstr "Регистрирует хендлер запросов на вступление в чат." @@ -3774,6 +3976,16 @@ msgstr "Регистрирует хендлер сообщений." msgid "List of chat types" msgstr "Список видов чатов" +#: of telebot.TeleBot.register_message_reaction_count_handler:1 +#, fuzzy +msgid "Registers message reaction count handler." +msgstr "Регистрирует хендлер сообщений." + +#: of telebot.TeleBot.register_message_reaction_handler:1 +#, fuzzy +msgid "Registers message reaction handler." +msgstr "Регистрирует хендлер сообщений." + #: of telebot.TeleBot.register_middleware_handler:1 msgid "Adds function-based middleware handler." msgstr "Добавляет функцию-middleware." @@ -3863,6 +4075,11 @@ msgstr "Регистрирует хендлер изменений состоя msgid "Registers pre-checkout request handler." msgstr "Регистрирует хендлер pre-checkout query." +#: of telebot.TeleBot.register_removed_chat_boost_handler:1 +#, fuzzy +msgid "Registers removed chat boost handler." +msgstr "Регистрирует хендлер изменений статуса бота." + #: of telebot.TeleBot.register_shipping_query_handler:1 msgid "Registers shipping query handler." msgstr "Регистрирует хендлер shipping query." @@ -3871,6 +4088,15 @@ msgstr "Регистрирует хендлер shipping query." msgid "Deletes webhooks using set_webhook() function." msgstr "Удаляет вебхук, используя set_webhook()." +#: of telebot.TeleBot.removed_chat_boost_handler:1 +#, fuzzy +msgid "" +"Handles new incoming chat boost state. it passes " +":class:`telebot.types.ChatBoostRemoved` object." +msgstr "" +"Обрабатывает inline query. В качестве параметра, передаёт в декорируемую " +"функцию объект :class:`telebot.types.InlineQuery`." + #: of telebot.TeleBot.reopen_forum_topic:1 msgid "" "Use this method to reopen a closed topic in a forum supergroup chat. The " @@ -4223,7 +4449,7 @@ msgid "Animation height" msgstr "Высота гифки" #: of telebot.TeleBot.send_animation:22 telebot.TeleBot.send_video:20 -#: telebot.TeleBot.send_video_note:33 +#: telebot.TeleBot.send_video_note:36 msgid "" "Thumbnail of the file sent; can be ignored if thumbnail generation for " "the file is supported server-side. The thumbnail should be in JPEG format" @@ -4254,7 +4480,7 @@ msgstr "" msgid "Mode for parsing entities in the animation caption" msgstr "Режим форматирования подписи к гифке" -#: of telebot.TeleBot.send_animation:51 telebot.TeleBot.send_video:29 +#: of telebot.TeleBot.send_animation:54 telebot.TeleBot.send_video:29 msgid "" "List of special entities that appear in the caption, which can be " "specified instead of parse_mode" @@ -4270,10 +4496,13 @@ msgstr "id топика, в который будет отправлено ви msgid "Pass True, if the animation should be sent as a spoiler" msgstr "Передайте True, если гифку нужно отправить как спойлер" -#: of telebot.TeleBot.send_animation:63 telebot.TeleBot.send_audio:63 -#: telebot.TeleBot.send_document:56 telebot.TeleBot.send_video:64 -#: telebot.TeleBot.send_video_note:48 -msgid "Deprecated. Use thumbnail instead" +#: of telebot.TeleBot.send_animation:66 telebot.TeleBot.send_audio:66 +#: telebot.TeleBot.send_contact:43 telebot.TeleBot.send_document:59 +#: telebot.TeleBot.send_location:49 telebot.TeleBot.send_media_group:30 +#: telebot.TeleBot.send_message:46 telebot.TeleBot.send_sticker:42 +#: telebot.TeleBot.send_venue:56 telebot.TeleBot.send_video_note:51 +#: telebot.TeleBot.send_voice:49 +msgid "Reply parameters." msgstr "" #: of telebot.TeleBot.send_audio:1 @@ -4328,7 +4557,7 @@ msgstr "Исполнитель" msgid "Track name" msgstr "Название трека" -#: of telebot.TeleBot.send_audio:36 +#: of telebot.TeleBot.send_audio:33 msgid "" "Mode for parsing entities in the audio caption. See formatting options " "for more details." @@ -4336,7 +4565,7 @@ msgstr "" "Режим форматирования подписи к аудио. См. formatting options для " "получения подробностей." -#: of telebot.TeleBot.send_audio:45 +#: of telebot.TeleBot.send_audio:48 msgid "" "Thumbnail of the file sent; can be ignored if thumbnail generation for " "the file is supported server-side. The thumbnail should be in JPEG format" @@ -4355,8 +4584,8 @@ msgstr "" "“attach://” если обложка была загружена с помощью " "multipart/form-data под именем ." -#: of telebot.TeleBot.send_audio:51 telebot.TeleBot.send_document:35 -#: telebot.TeleBot.send_photo:19 telebot.TeleBot.send_voice:37 +#: of telebot.TeleBot.send_audio:54 telebot.TeleBot.send_document:38 +#: telebot.TeleBot.send_photo:19 telebot.TeleBot.send_voice:40 msgid "" "A JSON-serialized list of special entities that appear in the caption, " "which can be specified instead of parse_mode" @@ -4393,12 +4622,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendchataction" msgstr "Документация Telegram: https://core.telegram.org/bots/api#sendchataction" -#: of telebot.TeleBot.send_chat_action:10 telebot.TeleBot.send_contact:5 -#: telebot.TeleBot.send_poll:6 telebot.TeleBot.send_venue:5 -#: telebot.TeleBot.stop_poll:5 -msgid "Unique identifier for the target chat or username of the target channel" -msgstr "Уникальный id чата или username канала" - #: of telebot.TeleBot.send_chat_action:13 msgid "" "Type of action to broadcast. Choose one, depending on what the user is " @@ -4449,16 +4672,7 @@ msgstr "Фамилия контакта" msgid "Additional data about the contact in the form of a vCard, 0-2048 bytes" msgstr "Дополнительные данные о контакте в формате vCard, 0-2048 байт" -#: of telebot.TeleBot.send_contact:34 telebot.TeleBot.send_game:23 -#: telebot.TeleBot.send_venue:41 -msgid "" -"Pass True, if the message should be sent even if one of the specified " -"replied-to messages is not found." -msgstr "" -"Передайте True, если сообщение должно быть отправлено даже если одно из " -"сообщений, на которые нужно ответить, не найдено." - -#: of telebot.TeleBot.send_contact:41 telebot.TeleBot.send_venue:54 +#: of telebot.TeleBot.send_contact:40 telebot.TeleBot.send_venue:53 msgid "The thread identifier of a message from which the reply will be sent" msgstr "id топика, на сообщение из которого нужно ответить" @@ -4486,10 +4700,6 @@ msgstr "" "одним из “🎲”, “🎯”, “🏀”, “⚽”, “🎳”, или “🎰”. Значение может быть 1-6 для " "“🎲”, “🎯” и “🎳”, 1-5 для “🏀” и “⚽”, и 1-64 для “🎰”. По умолчанию “🎲”" -#: of telebot.TeleBot.send_dice:29 -msgid "Protects the contents of the sent message from forwarding" -msgstr "Защищает содержимое отправленного сообщения от пересылки" - #: of telebot.TeleBot.send_document:1 msgid "Use this method to send general files." msgstr "Используйте этот метод, чтобы отправить файл." @@ -4510,7 +4720,7 @@ msgstr "" "передайте HTTP URL (String), чтобы отправить файл из интернета или " "загрузите новый с помощью multipart/form-data" -#: of telebot.TeleBot.send_document:15 +#: of telebot.TeleBot.send_document:12 msgid "" "Document caption (may also be used when resending documents by file_id), " "0-1024 characters after entities parsing" @@ -4518,11 +4728,11 @@ msgstr "" "Подпись к файлу (может быть использована при повторной отправке файла по " "file_id), 0-1024 символа после форматирования" -#: of telebot.TeleBot.send_document:23 +#: of telebot.TeleBot.send_document:20 msgid "Mode for parsing entities in the document caption" msgstr "Режим форматирования частей подписи к файлу" -#: of telebot.TeleBot.send_document:32 +#: of telebot.TeleBot.send_document:35 msgid "" "InputFile or String : Thumbnail of the file sent; can be ignored if " "thumbnail generation for the file is supported server-side. The thumbnail" @@ -4583,17 +4793,25 @@ msgstr "" "Короткое имя игры, служит в качестве уникального id игры. Настройте свои " "игрычерез @BotFather." -#: of telebot.TeleBot.send_game:20 -msgid "Timeout in seconds for waiting for a response from the bot." -msgstr "Тайм-аут в секундах, ожидание ответа от бота." +#: of telebot.TeleBot.send_game:14 telebot.TeleBot.send_invoice:70 +#: telebot.TeleBot.send_poll:47 +#, fuzzy +msgid "deprecated. If the message is a reply, ID of the original message" +msgstr "Если сообщение является ответом - id сообщения, на которое дан ответ" -#: of telebot.TeleBot.send_game:26 +#: of telebot.TeleBot.send_game:17 telebot.TeleBot.send_invoice:73 +#: telebot.TeleBot.send_poll:50 +#, fuzzy msgid "" -"Pass True, if content of the message needs to be protected from being " -"viewed by the bot." +"deprecated. Pass True, if the message should be sent even if the " +"specified replied-to message is not found" msgstr "" -"Передайте True, если содержимое сообщение должно быть защищено от " -"просмотра ботом." +"Передайте True, если сообщение нужно отправить даже в случае отсутствия " +"сообщения, на которое дан ответ" + +#: of telebot.TeleBot.send_game:23 +msgid "Timeout in seconds for waiting for a response from the bot." +msgstr "Тайм-аут в секундах, ожидание ответа от бота." #: of telebot.TeleBot.send_game:29 msgid "" @@ -4601,8 +4819,12 @@ msgid "" "sent." msgstr "id топика, в который будет отправлено сообщение с игрой." -#: of telebot.TeleBot.send_game:33 telebot.TeleBot.send_invoice:102 -#: telebot.TeleBot.send_poll:71 +#: of telebot.TeleBot.send_game:32 telebot.TeleBot.send_video:67 +msgid "Reply parameters" +msgstr "" + +#: of telebot.TeleBot.send_game:36 telebot.TeleBot.send_invoice:105 +#: telebot.TeleBot.send_poll:74 msgid ":obj:`types.Message`" msgstr "" @@ -4635,7 +4857,7 @@ msgstr "" "URL фото продукта. Может быть фото товаров или рекламным изображением " "сервиса. Людям больше нравится, когда они видят, за что платят." -#: of telebot.TeleBot.send_invoice:73 +#: of telebot.TeleBot.send_invoice:76 msgid "" "A JSON-serialized object for an inline keyboard. If empty, one 'Pay total" " price' button will be shown. If not empty, the first button must be a " @@ -4645,7 +4867,7 @@ msgstr "" "показана одна кнопка 'Pay total price'. Если не пустой, первая кнопка " "должна быть кнопкой для оплаты" -#: of telebot.TeleBot.send_invoice:81 telebot.TeleBot.set_webhook:39 +#: of telebot.TeleBot.send_invoice:84 telebot.TeleBot.set_webhook:39 msgid "Timeout of a request, defaults to None" msgstr "Тайм-аут запроса, по умолчанию None" @@ -4655,6 +4877,10 @@ msgid "" "sent" msgstr "id топика, в который будет отправлен инвойс" +#: of telebot.TeleBot.send_invoice:101 +msgid "Required if the message is a reply. Additional interface options." +msgstr "" + #: of telebot.TeleBot.send_location:1 msgid "" "Use this method to send point on the map. On success, the sent Message is" @@ -4683,7 +4909,7 @@ msgstr "" "Время в секундах, в течение которого местоположение будет обновляться " "(см. Live Locations), должно быть между 60 и 86400." -#: of telebot.TeleBot.send_location:34 +#: of telebot.TeleBot.send_location:37 msgid "" "For live locations, a direction in which the user is moving, in degrees. " "Must be between 1 and 360 if specified." @@ -4691,7 +4917,7 @@ msgstr "" "Для live местоположений, направление, в котором пользователь двигается, в" " градусах. Должно быть между 1 и 360, если указано." -#: of telebot.TeleBot.send_location:37 +#: of telebot.TeleBot.send_location:40 msgid "" "For live locations, a maximum distance for proximity alerts about " "approaching another chat member, in meters. Must be between 1 and 100000 " @@ -4737,7 +4963,7 @@ msgstr "" msgid "Identifier of a message thread, in which the media group will be sent" msgstr "id топика, в который будет отправлена группа медиа" -#: of telebot.TeleBot.send_media_group:30 +#: of telebot.TeleBot.send_media_group:33 msgid "On success, an array of Messages that were sent is returned." msgstr "В случае успеха возвращается массив отправленных сообщений (Message)." @@ -4772,13 +4998,9 @@ msgstr "" "Список отформатированных частей в тексте сообщения, можно использовать " "вместо parse_mode" -#: of telebot.TeleBot.send_message:27 -msgid "" -"If True, the message content will be hidden for all users except for the " -"target user" +#: of telebot.TeleBot.send_message:49 +msgid "Link preview options." msgstr "" -"Если True, содержимое сообщения будет скрыто от всех пользователей, кроме" -" заданного" #: of telebot.TeleBot.send_photo:1 msgid "Use this method to send photos. On success, the sent Message is returned." @@ -4906,12 +5128,6 @@ msgstr "" "Передайте True, если опрос должен быть завершен немедленно. Может быть " "полезно для предпросмотра опроса." -#: of telebot.TeleBot.send_poll:50 -msgid "Pass True, if the poll allows multiple options to be voted simultaneously." -msgstr "" -"Передайте True, если опрос позволяет выбрать несколько вариантов " -"одновременно." - #: of telebot.TeleBot.send_poll:57 msgid "Timeout in seconds for waiting for a response from the user." msgstr "Тайм-аут в секундах, ожидание ответа от пользователя." @@ -4928,6 +5144,10 @@ msgstr "" msgid "The identifier of a message thread, in which the poll will be sent" msgstr "id топика, в который будет отправлен опрос" +#: of telebot.TeleBot.send_poll:70 +msgid "reply parameters." +msgstr "" + #: of telebot.TeleBot.send_sticker:1 msgid "" "Use this method to send static .WEBP, animated .TGS, or video .WEBM " @@ -4953,7 +5173,7 @@ msgstr "" "URL (String), чтобы отправить .webp файл из интернета или загрузите новый" " с помощью multipart/form-data." -#: of telebot.TeleBot.send_sticker:21 +#: of telebot.TeleBot.send_sticker:18 msgid "to disable the notification" msgstr "отключить уведомление" @@ -5003,11 +5223,11 @@ msgstr "" "“arts_entertainment/default”, “arts_entertainment/aquarium” или " "“food/icecream”.)" -#: of telebot.TeleBot.send_venue:45 +#: of telebot.TeleBot.send_venue:44 msgid "Google Places identifier of the venue" msgstr "id места на Google Places" -#: of telebot.TeleBot.send_venue:48 +#: of telebot.TeleBot.send_venue:47 msgid "Google Places type of the venue." msgstr "Тип места на Google Places." @@ -5081,22 +5301,6 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#sendvideonote" msgstr "Документация Telegram: https://core.telegram.org/bots/api#sendvideonote" -#: of telebot.TeleBot.send_video_note -msgid "param chat_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type chat_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note:7 -msgid ":obj:`int` or :obj:`str`" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param data" -msgstr "" - #: of telebot.TeleBot.send_video_note:9 msgid "" "Video note to send. Pass a file_id as String to send a video note that " @@ -5109,120 +5313,14 @@ msgstr "" "новую с помощью multipart/form-data. На текущий момент, отправка видео " "заметок по URL не поддерживается" -#: of telebot.TeleBot.send_video_note -#, fuzzy -msgid "type data" -msgstr "тип" - -#: of telebot.TeleBot.send_video_note:11 telebot.TeleBot.send_video_note:37 -#, fuzzy -msgid ":obj:`str` or :class:`telebot.types.InputFile`" -msgstr "Список объектов :class:`telebot.types.Update`." - -#: of telebot.TeleBot.send_video_note -msgid "param duration" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type duration" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param length" -msgstr "" - #: of telebot.TeleBot.send_video_note:16 msgid "Video width and height, i.e. diameter of the video message" msgstr "Ширина и высота видео (диаметр видео сообщения)" -#: of telebot.TeleBot.send_video_note -msgid "type length" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param reply_to_message_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type reply_to_message_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param reply_markup" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type reply_markup" -msgstr "" - -#: of telebot.TeleBot.send_video_note:24 -msgid "" -":class:`telebot.types.InlineKeyboardMarkup` or " -":class:`telebot.types.ReplyKeyboardMarkup` or " -":class:`telebot.types.ReplyKeyboardRemove` or " -":class:`telebot.types.ForceReply`" -msgstr "" - -#: of telebot.TeleBot.send_video_note -#, fuzzy -msgid "param disable_notification" -msgstr "отключить уведомление" - -#: of telebot.TeleBot.send_video_note -#, fuzzy -msgid "type disable_notification" -msgstr "отключить уведомление" - -#: of telebot.TeleBot.send_video_note -msgid "param timeout" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type timeout" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param thumbnail" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type thumbnail" -msgstr "" - -#: of telebot.TeleBot.send_video_note -#, fuzzy -msgid "param allow_sending_without_reply" -msgstr "Глобальное значение allow_sending_without_reply, по умолчанию None" - -#: of telebot.TeleBot.send_video_note -#, fuzzy -msgid "type allow_sending_without_reply" -msgstr "Глобальное значение allow_sending_without_reply, по умолчанию None" - -#: of telebot.TeleBot.send_video_note -msgid "param protect_content" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "type protect_content" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param message_thread_id" -msgstr "" - #: of telebot.TeleBot.send_video_note:45 msgid "Identifier of a message thread, in which the video note will be sent" msgstr "id топика, в который будет отправлена видео заметка" -#: of telebot.TeleBot.send_video_note -msgid "type message_thread_id" -msgstr "" - -#: of telebot.TeleBot.send_video_note -msgid "param thumb" -msgstr "" - #: of telebot.TeleBot.send_voice:1 msgid "" "Use this method to send audio files, if you want Telegram clients to " @@ -5263,7 +5361,7 @@ msgstr "Подпись к голосовому сообщению, 0-1024 сим msgid "Duration of the voice message in seconds" msgstr "Длительность голосового сообщения в секундах" -#: of telebot.TeleBot.send_voice:28 +#: of telebot.TeleBot.send_voice:25 msgid "" "Mode for parsing entities in the voice message caption. See formatting " "options for more details." @@ -5496,6 +5594,43 @@ msgstr "" "В случае успеха, если сообщение было отправлено ботом, возвращает " "измененное сообщение (Message), иначе возвращает True." +#: of telebot.TeleBot.set_message_reaction:1 +#, fuzzy +msgid "" +"Use this method to set a reaction to a message in a chat. The bot must be" +" an administrator in the chat for this to work and must have the " +"appropriate admin rights. Returns True on success." +msgstr "" +"Используйте этот метод, чтобы закрепить сообщение в супергруппе. Бот " +"должен быть администратором чата и иметь соответствующие права " +"администратора. Возвращает True в случае успеха." + +#: of telebot.TeleBot.set_message_reaction:3 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#setmessagereaction" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#editmessagecaption" + +#: of telebot.TeleBot.set_message_reaction:8 +#, fuzzy +msgid "Identifier of the message to set reaction to" +msgstr "id сообщения, которое нужно удалить" + +#: of telebot.TeleBot.set_message_reaction:11 +msgid "" +"New list of reaction types to set on the message. Currently, as non-" +"premium users, bots can set up to one reaction per message. A custom " +"emoji reaction can be used if it is either already present on the message" +" or explicitly allowed by chat administrators." +msgstr "" + +#: of telebot.TeleBot.set_message_reaction:15 +msgid "Pass True to set the reaction with a big animation" +msgstr "" + #: of telebot.TeleBot.set_my_commands:1 msgid "Use this method to change the list of the bot's commands." msgstr "Используйте этот метод, чтобы изменить список команд бота." @@ -6141,6 +6276,32 @@ msgstr "" msgid "Identifier of the topic" msgstr "id топика" +#: of telebot.TeleBot.unpin_all_general_forum_topic_messages:1 +#, fuzzy +msgid "" +"Use this method to clear the list of pinned messages in a General forum " +"topic. The bot must be an administrator in the chat for this to work and " +"must have the can_pin_messages administrator right in the supergroup. " +"Returns True on success." +msgstr "" +"Используйте этот метод, что открепить все закрепленные сообщения в " +"топике. Бот должен быть администратором чата и иметь права администратора" +" can_pin_messages в супергруппе. Возвращает True в случае успеха." + +#: of telebot.TeleBot.unpin_all_general_forum_topic_messages:6 +#, fuzzy +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#unpinAllGeneralForumTopicMessages" +msgstr "" +"Документация Telegram: " +"https://core.telegram.org/bots/api#unpinallforumtopicmessages" + +#: of telebot.TeleBot.unpin_all_general_forum_topic_messages:8 +#, fuzzy +msgid "Unique identifier for the target chat or username of chat" +msgstr "Уникальный id чата или username канала" + #: of telebot.TeleBot.unpin_chat_message:1 msgid "" "Use this method to unpin specific pinned message in a supergroup chat. " @@ -6502,3 +6663,141 @@ msgstr "" #~ "Возвращает True в случае успешного " #~ "добавления." +#~ msgid "Disables link previews for links in this message" +#~ msgstr "Отключает превью ссылок в сообщении" + +#~ msgid "Deprecated, use non_stop. Old typo, kept for backward compatibility." +#~ msgstr "" +#~ "Устарело, используйте non_stop. Старая " +#~ "опечатка, оставлено для обратной совместимости" + +#~ msgid "Deprecated. Use thumbnail instead" +#~ msgstr "" + +#~ msgid "" +#~ "Pass True, if the message should " +#~ "be sent even if one of the " +#~ "specified replied-to messages is not " +#~ "found." +#~ msgstr "" +#~ "Передайте True, если сообщение должно " +#~ "быть отправлено даже если одно из " +#~ "сообщений, на которые нужно ответить, не" +#~ " найдено." + +#~ msgid "Protects the contents of the sent message from forwarding" +#~ msgstr "Защищает содержимое отправленного сообщения от пересылки" + +#~ msgid "" +#~ "Pass True, if content of the " +#~ "message needs to be protected from " +#~ "being viewed by the bot." +#~ msgstr "" +#~ "Передайте True, если содержимое сообщение " +#~ "должно быть защищено от просмотра ботом." + +#~ msgid "" +#~ "If True, the message content will " +#~ "be hidden for all users except for" +#~ " the target user" +#~ msgstr "" +#~ "Если True, содержимое сообщения будет " +#~ "скрыто от всех пользователей, кроме " +#~ "заданного" + +#~ msgid "" +#~ "Pass True, if the poll allows " +#~ "multiple options to be voted " +#~ "simultaneously." +#~ msgstr "" +#~ "Передайте True, если опрос позволяет " +#~ "выбрать несколько вариантов одновременно." + +#~ msgid "param chat_id" +#~ msgstr "" + +#~ msgid "type chat_id" +#~ msgstr "" + +#~ msgid ":obj:`int` or :obj:`str`" +#~ msgstr "" + +#~ msgid "param data" +#~ msgstr "" + +#~ msgid "type data" +#~ msgstr "тип" + +#~ msgid ":obj:`str` or :class:`telebot.types.InputFile`" +#~ msgstr "Список объектов :class:`telebot.types.Update`." + +#~ msgid "param duration" +#~ msgstr "" + +#~ msgid "type duration" +#~ msgstr "" + +#~ msgid "param length" +#~ msgstr "" + +#~ msgid "type length" +#~ msgstr "" + +#~ msgid "param reply_to_message_id" +#~ msgstr "" + +#~ msgid "type reply_to_message_id" +#~ msgstr "" + +#~ msgid "param reply_markup" +#~ msgstr "" + +#~ msgid "type reply_markup" +#~ msgstr "" + +#~ msgid "" +#~ ":class:`telebot.types.InlineKeyboardMarkup` or " +#~ ":class:`telebot.types.ReplyKeyboardMarkup` or " +#~ ":class:`telebot.types.ReplyKeyboardRemove` or " +#~ ":class:`telebot.types.ForceReply`" +#~ msgstr "" + +#~ msgid "param disable_notification" +#~ msgstr "отключить уведомление" + +#~ msgid "type disable_notification" +#~ msgstr "отключить уведомление" + +#~ msgid "param timeout" +#~ msgstr "" + +#~ msgid "type timeout" +#~ msgstr "" + +#~ msgid "param thumbnail" +#~ msgstr "" + +#~ msgid "type thumbnail" +#~ msgstr "" + +#~ msgid "param allow_sending_without_reply" +#~ msgstr "Глобальное значение allow_sending_without_reply, по умолчанию None" + +#~ msgid "type allow_sending_without_reply" +#~ msgstr "Глобальное значение allow_sending_without_reply, по умолчанию None" + +#~ msgid "param protect_content" +#~ msgstr "" + +#~ msgid "type protect_content" +#~ msgstr "" + +#~ msgid "param message_thread_id" +#~ msgstr "" + +#~ msgid "type message_thread_id" +#~ msgstr "" + +#~ msgid "param thumb" +#~ msgstr "" + diff --git a/docs/source/locales/ru/LC_MESSAGES/types.po b/docs/source/locales/ru/LC_MESSAGES/types.po index c846273fe..1dfef7706 100644 --- a/docs/source/locales/ru/LC_MESSAGES/types.po +++ b/docs/source/locales/ru/LC_MESSAGES/types.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-08 23:07+0500\n" +"POT-Creation-Date: 2024-01-05 22:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -25,26 +25,35 @@ msgstr "" #: of telebot.types.Animation:1 telebot.types.Audio:1 #: telebot.types.BotDescription:1 telebot.types.BotName:1 #: telebot.types.BotShortDescription:1 telebot.types.CallbackQuery:1 -#: telebot.types.Chat:1 telebot.types.ChatJoinRequest:1 +#: telebot.types.Chat:1 telebot.types.ChatBoost:1 +#: telebot.types.ChatBoostRemoved:1 telebot.types.ChatBoostSource:1 +#: telebot.types.ChatBoostUpdated:1 telebot.types.ChatJoinRequest:1 #: telebot.types.ChatMember:1 telebot.types.ChatMemberUpdated:1 #: telebot.types.ChatPhoto:1 telebot.types.ChatShared:1 #: telebot.types.ChosenInlineResult:1 telebot.types.Contact:1 -#: telebot.types.Document:1 telebot.types.File:1 telebot.types.ForumTopic:1 +#: telebot.types.Document:1 telebot.types.ExternalReplyInfo:1 +#: telebot.types.File:1 telebot.types.ForumTopic:1 #: telebot.types.ForumTopicClosed:1 telebot.types.ForumTopicCreated:1 #: telebot.types.ForumTopicEdited:1 telebot.types.ForumTopicReopened:1 #: telebot.types.Game:1 telebot.types.GameHighScore:1 #: telebot.types.GeneralForumTopicHidden:1 -#: telebot.types.GeneralForumTopicUnhidden:1 telebot.types.InlineQuery:1 -#: telebot.types.Invoice:1 telebot.types.Message:1 +#: telebot.types.GeneralForumTopicUnhidden:1 telebot.types.Giveaway:1 +#: telebot.types.GiveawayCompleted:1 telebot.types.GiveawayCreated:1 +#: telebot.types.GiveawayWinners:1 telebot.types.InaccessibleMessage:1 +#: telebot.types.InlineQuery:1 telebot.types.Invoice:1 telebot.types.Message:1 #: telebot.types.MessageAutoDeleteTimerChanged:1 telebot.types.MessageID:1 -#: telebot.types.OrderInfo:1 telebot.types.PhotoSize:1 telebot.types.Poll:1 -#: telebot.types.PollOption:1 telebot.types.PreCheckoutQuery:1 -#: telebot.types.ProximityAlertTriggered:1 telebot.types.ShippingAddress:1 +#: telebot.types.MessageOrigin:1 telebot.types.MessageReactionCountUpdated:1 +#: telebot.types.MessageReactionUpdated:1 telebot.types.OrderInfo:1 +#: telebot.types.PhotoSize:1 telebot.types.Poll:1 telebot.types.PollOption:1 +#: telebot.types.PreCheckoutQuery:1 telebot.types.ProximityAlertTriggered:1 +#: telebot.types.ReactionCount:1 telebot.types.ShippingAddress:1 #: telebot.types.ShippingQuery:1 telebot.types.Sticker:1 -#: telebot.types.StickerSet:1 telebot.types.SuccessfulPayment:1 -#: telebot.types.Update:1 telebot.types.UserProfilePhotos:1 -#: telebot.types.UserShared:1 telebot.types.Venue:1 telebot.types.Video:1 -#: telebot.types.VideoChatEnded:1 telebot.types.VideoChatParticipantsInvited:1 +#: telebot.types.StickerSet:1 telebot.types.Story:1 +#: telebot.types.SuccessfulPayment:1 telebot.types.TextQuote:1 +#: telebot.types.Update:1 telebot.types.UserChatBoosts:1 +#: telebot.types.UserProfilePhotos:1 telebot.types.UsersShared:1 +#: telebot.types.Venue:1 telebot.types.Video:1 telebot.types.VideoChatEnded:1 +#: telebot.types.VideoChatParticipantsInvited:1 #: telebot.types.VideoChatScheduled:1 telebot.types.VideoChatStarted:1 #: telebot.types.VideoNote:1 telebot.types.Voice:1 telebot.types.WebhookInfo:1 #: telebot.types.WriteAccessAllowed:1 @@ -71,19 +80,24 @@ msgstr "" #: telebot.types.BotDescription telebot.types.BotName #: telebot.types.BotShortDescription telebot.types.CallbackQuery #: telebot.types.Chat telebot.types.ChatAdministratorRights -#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest -#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator -#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft -#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner -#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated -#: telebot.types.ChatPermissions telebot.types.ChatPhoto -#: telebot.types.ChatShared telebot.types.ChosenInlineResult -#: telebot.types.Contact telebot.types.Dice telebot.types.Document -#: telebot.types.File telebot.types.ForceReply telebot.types.ForumTopic +#: telebot.types.ChatBoost telebot.types.ChatBoostRemoved +#: telebot.types.ChatBoostSource telebot.types.ChatBoostSourceGiftCode +#: telebot.types.ChatBoostSourceGiveaway telebot.types.ChatBoostSourcePremium +#: telebot.types.ChatBoostUpdated telebot.types.ChatInviteLink +#: telebot.types.ChatJoinRequest telebot.types.ChatLocation +#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned +#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember +#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted +#: telebot.types.ChatMemberUpdated telebot.types.ChatPermissions +#: telebot.types.ChatPhoto telebot.types.ChatShared +#: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice +#: telebot.types.Document telebot.types.ExternalReplyInfo telebot.types.File +#: telebot.types.ForceReply telebot.types.ForumTopic #: telebot.types.ForumTopicCreated telebot.types.ForumTopicEdited -#: telebot.types.Game telebot.types.GameHighScore -#: telebot.types.InlineKeyboardButton telebot.types.InlineKeyboardMarkup -#: telebot.types.InlineKeyboardMarkup.add +#: telebot.types.Game telebot.types.GameHighScore telebot.types.Giveaway +#: telebot.types.GiveawayCompleted telebot.types.GiveawayWinners +#: telebot.types.InaccessibleMessage telebot.types.InlineKeyboardButton +#: telebot.types.InlineKeyboardMarkup telebot.types.InlineKeyboardMarkup.add #: telebot.types.InlineKeyboardMarkup.row telebot.types.InlineQuery #: telebot.types.InlineQueryResultArticle telebot.types.InlineQueryResultAudio #: telebot.types.InlineQueryResultCachedAudio @@ -109,23 +123,32 @@ msgstr "" #: telebot.types.InputVenueMessageContent telebot.types.Invoice #: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType #: telebot.types.KeyboardButtonRequestChat -#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice -#: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition +#: telebot.types.KeyboardButtonRequestUsers telebot.types.LabeledPrice +#: telebot.types.LinkPreviewOptions telebot.types.Location +#: telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message #: telebot.types.MessageAutoDeleteTimerChanged telebot.types.MessageEntity -#: telebot.types.MessageID telebot.types.OrderInfo telebot.types.PhotoSize -#: telebot.types.Poll telebot.types.Poll.add telebot.types.PollAnswer -#: telebot.types.PollOption telebot.types.PreCheckoutQuery -#: telebot.types.ProximityAlertTriggered telebot.types.ReplyKeyboardMarkup -#: telebot.types.ReplyKeyboardMarkup.add telebot.types.ReplyKeyboardMarkup.row -#: telebot.types.ReplyKeyboardRemove telebot.types.SentWebAppMessage +#: telebot.types.MessageID telebot.types.MessageOrigin +#: telebot.types.MessageOriginChannel telebot.types.MessageOriginChat +#: telebot.types.MessageOriginHiddenUser telebot.types.MessageOriginUser +#: telebot.types.MessageReactionCountUpdated +#: telebot.types.MessageReactionUpdated telebot.types.OrderInfo +#: telebot.types.PhotoSize telebot.types.Poll telebot.types.Poll.add +#: telebot.types.PollAnswer telebot.types.PollOption +#: telebot.types.PreCheckoutQuery telebot.types.ProximityAlertTriggered +#: telebot.types.ReactionCount telebot.types.ReactionType +#: telebot.types.ReactionTypeCustomEmoji telebot.types.ReactionTypeEmoji +#: telebot.types.ReplyKeyboardMarkup telebot.types.ReplyKeyboardMarkup.add +#: telebot.types.ReplyKeyboardMarkup.row telebot.types.ReplyKeyboardRemove +#: telebot.types.ReplyParameters telebot.types.SentWebAppMessage #: telebot.types.ShippingAddress telebot.types.ShippingOption #: telebot.types.ShippingOption.add_price telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet #: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat -#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos -#: telebot.types.UserShared telebot.types.Venue telebot.types.Video +#: telebot.types.TextQuote telebot.types.Update telebot.types.User +#: telebot.types.UserChatBoosts telebot.types.UserProfilePhotos +#: telebot.types.UsersShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -194,17 +217,23 @@ msgstr "" #: telebot.types.BotDescription telebot.types.BotName #: telebot.types.BotShortDescription telebot.types.CallbackQuery #: telebot.types.Chat telebot.types.ChatAdministratorRights -#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest -#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator -#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft -#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner -#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated -#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions -#: telebot.types.ChatPhoto telebot.types.ChatShared -#: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice -#: telebot.types.Document telebot.types.File telebot.types.ForceReply +#: telebot.types.ChatBoost telebot.types.ChatBoostRemoved +#: telebot.types.ChatBoostSource telebot.types.ChatBoostSourceGiftCode +#: telebot.types.ChatBoostSourceGiveaway telebot.types.ChatBoostSourcePremium +#: telebot.types.ChatBoostUpdated telebot.types.ChatInviteLink +#: telebot.types.ChatJoinRequest telebot.types.ChatLocation +#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned +#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember +#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted +#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference +#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.ChatShared telebot.types.ChosenInlineResult +#: telebot.types.Contact telebot.types.Dice telebot.types.Document +#: telebot.types.ExternalReplyInfo telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game -#: telebot.types.GameHighScore telebot.types.InlineKeyboardButton +#: telebot.types.GameHighScore telebot.types.Giveaway +#: telebot.types.GiveawayCompleted telebot.types.GiveawayWinners +#: telebot.types.InaccessibleMessage telebot.types.InlineKeyboardButton #: telebot.types.InlineKeyboardMarkup telebot.types.InlineKeyboardMarkup.add #: telebot.types.InlineKeyboardMarkup.row telebot.types.InlineQuery #: telebot.types.InlineQueryResultArticle telebot.types.InlineQueryResultAudio @@ -231,22 +260,29 @@ msgstr "" #: telebot.types.InputVenueMessageContent telebot.types.Invoice #: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType #: telebot.types.KeyboardButtonRequestChat -#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice -#: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition +#: telebot.types.KeyboardButtonRequestUsers telebot.types.LabeledPrice +#: telebot.types.LinkPreviewOptions telebot.types.Location +#: telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message #: telebot.types.MessageAutoDeleteTimerChanged telebot.types.MessageEntity -#: telebot.types.MessageID telebot.types.OrderInfo telebot.types.PhotoSize -#: telebot.types.Poll telebot.types.PollAnswer telebot.types.PollOption -#: telebot.types.PreCheckoutQuery telebot.types.ProximityAlertTriggered -#: telebot.types.ReplyKeyboardMarkup telebot.types.ReplyKeyboardMarkup.add -#: telebot.types.ReplyKeyboardMarkup.row telebot.types.ReplyKeyboardRemove +#: telebot.types.MessageID telebot.types.MessageOrigin +#: telebot.types.MessageReactionCountUpdated +#: telebot.types.MessageReactionUpdated telebot.types.OrderInfo +#: telebot.types.PhotoSize telebot.types.Poll telebot.types.PollAnswer +#: telebot.types.PollOption telebot.types.PreCheckoutQuery +#: telebot.types.ProximityAlertTriggered telebot.types.ReactionCount +#: telebot.types.ReactionType telebot.types.ReactionTypeCustomEmoji +#: telebot.types.ReactionTypeEmoji telebot.types.ReplyKeyboardMarkup +#: telebot.types.ReplyKeyboardMarkup.add telebot.types.ReplyKeyboardMarkup.row +#: telebot.types.ReplyKeyboardRemove telebot.types.ReplyParameters #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingOption.add_price #: telebot.types.ShippingQuery telebot.types.Sticker telebot.types.StickerSet #: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat -#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos -#: telebot.types.UserShared telebot.types.Venue telebot.types.Video +#: telebot.types.TextQuote telebot.types.Update telebot.types.User +#: telebot.types.UserChatBoosts telebot.types.UserProfilePhotos +#: telebot.types.UsersShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -263,19 +299,26 @@ msgstr "" #: telebot.types.BotCommandScopeChatMember:15 #: telebot.types.BotCommandScopeDefault:8 telebot.types.BotDescription:8 #: telebot.types.BotName:8 telebot.types.BotShortDescription:8 -#: telebot.types.CallbackQuery:30 telebot.types.Chat:109 -#: telebot.types.ChatAdministratorRights:46 telebot.types.ChatInviteLink:34 -#: telebot.types.ChatJoinRequest:27 telebot.types.ChatLocation:11 -#: telebot.types.ChatMemberAdministrator:59 telebot.types.ChatMemberBanned:15 -#: telebot.types.ChatMemberLeft:11 telebot.types.ChatMemberMember:11 -#: telebot.types.ChatMemberOwner:17 telebot.types.ChatMemberRestricted:61 -#: telebot.types.ChatMemberUpdated:27 telebot.types.ChatPermissions:56 -#: telebot.types.ChatPhoto:21 telebot.types.ChatShared:15 -#: telebot.types.ChosenInlineResult:21 telebot.types.Contact:22 -#: telebot.types.Dice:11 telebot.types.Document:26 telebot.types.File:21 +#: telebot.types.CallbackQuery:29 telebot.types.Chat:137 +#: telebot.types.ChatAdministratorRights:55 telebot.types.ChatBoost:17 +#: telebot.types.ChatBoostRemoved:17 telebot.types.ChatBoostSource:8 +#: telebot.types.ChatBoostSourceGiftCode:11 +#: telebot.types.ChatBoostSourceGiveaway:17 +#: telebot.types.ChatBoostSourcePremium:11 telebot.types.ChatBoostUpdated:11 +#: telebot.types.ChatInviteLink:34 telebot.types.ChatJoinRequest:27 +#: telebot.types.ChatLocation:11 telebot.types.ChatMemberAdministrator:68 +#: telebot.types.ChatMemberBanned:15 telebot.types.ChatMemberLeft:11 +#: telebot.types.ChatMemberMember:11 telebot.types.ChatMemberOwner:17 +#: telebot.types.ChatMemberRestricted:61 telebot.types.ChatMemberUpdated:27 +#: telebot.types.ChatPermissions:55 telebot.types.ChatPhoto:21 +#: telebot.types.ChatShared:15 telebot.types.ChosenInlineResult:21 +#: telebot.types.Contact:22 telebot.types.Dice:11 telebot.types.Document:26 +#: telebot.types.ExternalReplyInfo:75 telebot.types.File:21 #: telebot.types.ForceReply:18 telebot.types.ForumTopic:17 #: telebot.types.ForumTopicCreated:14 telebot.types.Game:25 -#: telebot.types.GameHighScore:14 telebot.types.InlineKeyboardButton:49 +#: telebot.types.GameHighScore:14 telebot.types.Giveaway:29 +#: telebot.types.GiveawayCompleted:14 telebot.types.GiveawayWinners:38 +#: telebot.types.InaccessibleMessage:14 telebot.types.InlineKeyboardButton:49 #: telebot.types.InlineKeyboardMarkup:28 telebot.types.InlineQuery:26 #: telebot.types.InlineQueryResultArticle:38 #: telebot.types.InlineQueryResultAudio:40 @@ -303,28 +346,34 @@ msgstr "" #: telebot.types.InputMediaAnimation:40 telebot.types.InputMediaAudio:37 #: telebot.types.InputMediaDocument:32 telebot.types.InputMediaPhoto:24 #: telebot.types.InputMediaVideo:43 telebot.types.InputSticker:18 -#: telebot.types.InputTextMessageContent:19 +#: telebot.types.InputTextMessageContent:22 #: telebot.types.InputVenueMessageContent:30 telebot.types.Invoice:22 -#: telebot.types.KeyboardButton:33 telebot.types.KeyboardButtonPollType:9 +#: telebot.types.KeyboardButton:36 telebot.types.KeyboardButtonPollType:9 #: telebot.types.KeyboardButtonRequestChat:35 -#: telebot.types.KeyboardButtonRequestUser:18 telebot.types.LabeledPrice:13 -#: telebot.types.Location:25 telebot.types.LoginUrl:24 -#: telebot.types.MaskPosition:20 telebot.types.MenuButtonCommands:8 -#: telebot.types.MenuButtonDefault:8 telebot.types.MenuButtonWebApp:15 -#: telebot.types.Message:252 telebot.types.MessageAutoDeleteTimerChanged:8 -#: telebot.types.MessageEntity:32 telebot.types.MessageID:8 -#: telebot.types.OrderInfo:17 telebot.types.PhotoSize:21 telebot.types.Poll:47 -#: telebot.types.PollAnswer:15 telebot.types.PollOption:11 -#: telebot.types.PreCheckoutQuery:28 telebot.types.ProximityAlertTriggered:14 -#: telebot.types.ReplyKeyboardMarkup:49 telebot.types.ReplyKeyboardRemove:18 +#: telebot.types.KeyboardButtonRequestUsers:21 telebot.types.LabeledPrice:13 +#: telebot.types.LinkPreviewOptions:20 telebot.types.Location:25 +#: telebot.types.LoginUrl:24 telebot.types.MaskPosition:20 +#: telebot.types.MenuButtonCommands:8 telebot.types.MenuButtonDefault:8 +#: telebot.types.MenuButtonWebApp:15 telebot.types.Message:277 +#: telebot.types.MessageAutoDeleteTimerChanged:8 telebot.types.MessageEntity:32 +#: telebot.types.MessageID:8 telebot.types.MessageOrigin:23 +#: telebot.types.MessageReactionCountUpdated:17 +#: telebot.types.MessageReactionUpdated:26 telebot.types.OrderInfo:17 +#: telebot.types.PhotoSize:21 telebot.types.Poll:47 telebot.types.PollAnswer:18 +#: telebot.types.PollOption:11 telebot.types.PreCheckoutQuery:28 +#: telebot.types.ProximityAlertTriggered:14 telebot.types.ReactionCount:11 +#: telebot.types.ReactionType:8 telebot.types.ReactionTypeCustomEmoji:11 +#: telebot.types.ReactionTypeEmoji:11 telebot.types.ReplyKeyboardMarkup:49 +#: telebot.types.ReplyKeyboardRemove:18 telebot.types.ReplyParameters:26 #: telebot.types.SentWebAppMessage:9 telebot.types.ShippingAddress:23 #: telebot.types.ShippingOption:14 telebot.types.ShippingQuery:17 -#: telebot.types.Sticker:54 telebot.types.StickerSet:30 +#: telebot.types.Sticker:54 telebot.types.StickerSet:29 #: telebot.types.SuccessfulPayment:28 -#: telebot.types.SwitchInlineQueryChosenChat:22 telebot.types.Update:61 -#: telebot.types.User:41 telebot.types.UserProfilePhotos:11 -#: telebot.types.UserShared:15 telebot.types.Venue:27 telebot.types.Video:35 -#: telebot.types.VideoChatEnded:8 telebot.types.VideoChatParticipantsInvited:8 +#: telebot.types.SwitchInlineQueryChosenChat:22 telebot.types.TextQuote:17 +#: telebot.types.Update:75 telebot.types.User:41 telebot.types.UserChatBoosts:8 +#: telebot.types.UserProfilePhotos:11 telebot.types.UsersShared:17 +#: telebot.types.Venue:27 telebot.types.Video:35 telebot.types.VideoChatEnded:8 +#: telebot.types.VideoChatParticipantsInvited:8 #: telebot.types.VideoChatScheduled:9 telebot.types.VideoNote:24 #: telebot.types.Voice:23 telebot.types.WebAppData:12 #: telebot.types.WebAppInfo:8 telebot.types.WebhookInfo:37 @@ -342,17 +391,23 @@ msgstr "" #: telebot.types.BotDescription telebot.types.BotName #: telebot.types.BotShortDescription telebot.types.CallbackQuery #: telebot.types.Chat telebot.types.ChatAdministratorRights -#: telebot.types.ChatInviteLink telebot.types.ChatJoinRequest -#: telebot.types.ChatLocation telebot.types.ChatMemberAdministrator -#: telebot.types.ChatMemberBanned telebot.types.ChatMemberLeft -#: telebot.types.ChatMemberMember telebot.types.ChatMemberOwner -#: telebot.types.ChatMemberRestricted telebot.types.ChatMemberUpdated -#: telebot.types.ChatMemberUpdated.difference telebot.types.ChatPermissions -#: telebot.types.ChatPhoto telebot.types.ChatShared -#: telebot.types.ChosenInlineResult telebot.types.Contact telebot.types.Dice -#: telebot.types.Document telebot.types.File telebot.types.ForceReply +#: telebot.types.ChatBoost telebot.types.ChatBoostRemoved +#: telebot.types.ChatBoostSource telebot.types.ChatBoostSourceGiftCode +#: telebot.types.ChatBoostSourceGiveaway telebot.types.ChatBoostSourcePremium +#: telebot.types.ChatBoostUpdated telebot.types.ChatInviteLink +#: telebot.types.ChatJoinRequest telebot.types.ChatLocation +#: telebot.types.ChatMemberAdministrator telebot.types.ChatMemberBanned +#: telebot.types.ChatMemberLeft telebot.types.ChatMemberMember +#: telebot.types.ChatMemberOwner telebot.types.ChatMemberRestricted +#: telebot.types.ChatMemberUpdated telebot.types.ChatMemberUpdated.difference +#: telebot.types.ChatPermissions telebot.types.ChatPhoto +#: telebot.types.ChatShared telebot.types.ChosenInlineResult +#: telebot.types.Contact telebot.types.Dice telebot.types.Document +#: telebot.types.ExternalReplyInfo telebot.types.File telebot.types.ForceReply #: telebot.types.ForumTopic telebot.types.ForumTopicCreated telebot.types.Game -#: telebot.types.GameHighScore telebot.types.InlineKeyboardButton +#: telebot.types.GameHighScore telebot.types.Giveaway +#: telebot.types.GiveawayCompleted telebot.types.GiveawayWinners +#: telebot.types.InaccessibleMessage telebot.types.InlineKeyboardButton #: telebot.types.InlineKeyboardMarkup telebot.types.InlineKeyboardMarkup.add #: telebot.types.InlineKeyboardMarkup.row telebot.types.InlineQuery #: telebot.types.InlineQueryResultArticle telebot.types.InlineQueryResultAudio @@ -379,22 +434,29 @@ msgstr "" #: telebot.types.InputVenueMessageContent telebot.types.Invoice #: telebot.types.KeyboardButton telebot.types.KeyboardButtonPollType #: telebot.types.KeyboardButtonRequestChat -#: telebot.types.KeyboardButtonRequestUser telebot.types.LabeledPrice -#: telebot.types.Location telebot.types.LoginUrl telebot.types.MaskPosition +#: telebot.types.KeyboardButtonRequestUsers telebot.types.LabeledPrice +#: telebot.types.LinkPreviewOptions telebot.types.Location +#: telebot.types.LoginUrl telebot.types.MaskPosition #: telebot.types.MenuButtonCommands telebot.types.MenuButtonDefault #: telebot.types.MenuButtonWebApp telebot.types.Message #: telebot.types.MessageAutoDeleteTimerChanged telebot.types.MessageEntity -#: telebot.types.MessageID telebot.types.OrderInfo telebot.types.PhotoSize -#: telebot.types.Poll telebot.types.PollAnswer telebot.types.PollOption -#: telebot.types.PreCheckoutQuery telebot.types.ProximityAlertTriggered -#: telebot.types.ReplyKeyboardMarkup telebot.types.ReplyKeyboardMarkup.add -#: telebot.types.ReplyKeyboardMarkup.row telebot.types.ReplyKeyboardRemove +#: telebot.types.MessageID telebot.types.MessageOrigin +#: telebot.types.MessageReactionCountUpdated +#: telebot.types.MessageReactionUpdated telebot.types.OrderInfo +#: telebot.types.PhotoSize telebot.types.Poll telebot.types.PollAnswer +#: telebot.types.PollOption telebot.types.PreCheckoutQuery +#: telebot.types.ProximityAlertTriggered telebot.types.ReactionCount +#: telebot.types.ReactionType telebot.types.ReactionTypeCustomEmoji +#: telebot.types.ReactionTypeEmoji telebot.types.ReplyKeyboardMarkup +#: telebot.types.ReplyKeyboardMarkup.add telebot.types.ReplyKeyboardMarkup.row +#: telebot.types.ReplyKeyboardRemove telebot.types.ReplyParameters #: telebot.types.SentWebAppMessage telebot.types.ShippingAddress #: telebot.types.ShippingOption telebot.types.ShippingQuery #: telebot.types.Sticker telebot.types.StickerSet #: telebot.types.SuccessfulPayment telebot.types.SwitchInlineQueryChosenChat -#: telebot.types.Update telebot.types.User telebot.types.UserProfilePhotos -#: telebot.types.UserShared telebot.types.Venue telebot.types.Video +#: telebot.types.TextQuote telebot.types.Update telebot.types.User +#: telebot.types.UserChatBoosts telebot.types.UserProfilePhotos +#: telebot.types.UsersShared telebot.types.Venue telebot.types.Video #: telebot.types.VideoChatEnded telebot.types.VideoChatParticipantsInvited #: telebot.types.VideoChatScheduled telebot.types.VideoNote telebot.types.Voice #: telebot.types.WebAppData telebot.types.WebAppInfo telebot.types.WebhookInfo @@ -801,38 +863,37 @@ msgstr "" #: of telebot.types.CallbackQuery:11 msgid "" -"Optional. Message with the callback button that originated the query. " -"Note that message content and message date will not be available if the " -"message is too old" +"Optional. Message sent by the bot with the callback button that " +"originated the query" msgstr "" -#: of telebot.types.CallbackQuery:15 +#: of telebot.types.CallbackQuery:14 msgid "" "Optional. Identifier of the message sent via the bot in inline mode, that" " originated the query." msgstr "" -#: of telebot.types.CallbackQuery:19 +#: of telebot.types.CallbackQuery:18 msgid "" "Global identifier, uniquely corresponding to the chat to which the " "message with the callback button was sent. Useful for high scores in " "games." msgstr "" -#: of telebot.types.CallbackQuery:23 +#: of telebot.types.CallbackQuery:22 msgid "" "Optional. Data associated with the callback button. Be aware that the " "message originated the query can contain no callback buttons with this " "data." msgstr "" -#: of telebot.types.CallbackQuery:27 +#: of telebot.types.CallbackQuery:26 msgid "" "Optional. Short name of a Game to be returned, serves as the unique " "identifier for the game" msgstr "" -#: of telebot.types.CallbackQuery:31 +#: of telebot.types.CallbackQuery:30 msgid ":class:`telebot.types.CallbackQuery`" msgstr "" @@ -891,114 +952,159 @@ msgstr "" #: of telebot.types.Chat:35 msgid "" +"Optional. List of available chat reactions; for private chats, " +"supergroups and channels. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:39 +msgid "" +"Optional. Optional. Identifier of the accent color for the chat name and " +"backgrounds of the chat photo, reply header, and link preview. See accent" +" colors for more details. Returned only in getChat. Always returned in " +"getChat." +msgstr "" + +#: of telebot.types.Chat:43 +msgid "" +"Optional. Custom emoji identifier of emoji chosen by the chat for the " +"reply header and link preview background. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:47 +msgid "" +"Optional. Identifier of the accent color for the chat's profile " +"background. See profile accent colors for more details. Returned only in " +"getChat." +msgstr "" + +#: of telebot.types.Chat:51 +msgid "" +"Optional. Custom emoji identifier of the emoji chosen by the chat for its" +" profile background. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:55 +msgid "" "Optional. Custom emoji identifier of emoji status of the other party in a" " private chat. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:39 +#: of telebot.types.Chat:59 +msgid "" +"Optional. Expiration date of the emoji status of the other party in a " +"private chat, if any. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:63 msgid "" "Optional. Bio of the other party in a private chat. Returned only in " "getChat." msgstr "" -#: of telebot.types.Chat:42 +#: of telebot.types.Chat:66 msgid "" "Optional. :obj:`bool`, if privacy settings of the other party in the " "private chat allows to use tg://user?id= links only in chats " "with the user. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:46 +#: of telebot.types.Chat:70 msgid "" "Optional. True, if the privacy settings of the other party restrict " "sending voice and video note messages in the private chat. Returned only " "in getChat." msgstr "" -#: of telebot.types.Chat:48 +#: of telebot.types.Chat:72 msgid ":type :obj:`bool`" msgstr "" -#: of telebot.types.Chat:50 +#: of telebot.types.Chat:74 msgid "" "Optional. :obj:`bool`, if users need to join the supergroup before they " "can send messages. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:54 +#: of telebot.types.Chat:78 msgid "" "Optional. :obj:`bool`, if all users directly joining the supergroup need " "to be approved by supergroup administrators. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:58 +#: of telebot.types.Chat:82 msgid "" "Optional. Description, for groups, supergroups and channel chats. " "Returned only in getChat." msgstr "" -#: of telebot.types.Chat:61 +#: of telebot.types.Chat:85 msgid "" "Optional. Primary invite link, for groups, supergroups and channel chats." " Returned only in getChat." msgstr "" -#: of telebot.types.Chat:65 +#: of telebot.types.Chat:89 msgid "" "Optional. The most recent pinned message (by sending date). Returned only" " in getChat." msgstr "" -#: of telebot.types.Chat:68 +#: of telebot.types.Chat:92 msgid "" "Optional. Default chat member permissions, for groups and supergroups. " "Returned only in getChat." msgstr "" -#: of telebot.types.Chat:72 +#: of telebot.types.Chat:96 msgid "" "Optional. For supergroups, the minimum allowed delay between consecutive " "messages sent by each unpriviledged user; in seconds. Returned only in " "getChat." msgstr "" -#: of telebot.types.Chat:76 +#: of telebot.types.Chat:100 msgid "" "Optional. The time after which all messages sent to the chat will be " "automatically deleted; in seconds. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:80 +#: of telebot.types.Chat:104 msgid "" "Optional. :obj:`bool`, if the chat has enabled aggressive anti-spam " "protection. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:84 +#: of telebot.types.Chat:108 msgid "" "Optional. :obj:`bool`, if the chat has enabled hidden members. Returned " "only in getChat." msgstr "" -#: of telebot.types.Chat:88 +#: of telebot.types.Chat:112 msgid "" "Optional. :obj:`bool`, if messages from the chat can't be forwarded to " "other chats. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:92 +#: of telebot.types.Chat:116 +msgid "" +"Optional. True, if new chat members will have access to old messages; " +"available only to chat administrators. Returned only in getChat." +msgstr "" + +#: of telebot.types.Chat:120 msgid "" "Optional. For supergroups, name of group sticker set. Returned only in " "getChat." msgstr "" -#: of telebot.types.Chat:95 +#: of telebot.types.Chat:123 msgid "" "Optional. :obj:`bool`, if the bot can change the group sticker set. " "Returned only in getChat." msgstr "" -#: of telebot.types.Chat:99 +#: of telebot.types.Chat:127 msgid "" "Optional. Unique identifier for the linked chat, i.e. the discussion " "group identifier for a channel and vice versa; for supergroups and " @@ -1009,13 +1115,13 @@ msgid "" "in getChat." msgstr "" -#: of telebot.types.Chat:105 +#: of telebot.types.Chat:133 msgid "" "Optional. For supergroups, the location to which the supergroup is " "connected. Returned only in getChat." msgstr "" -#: of telebot.types.Chat:110 +#: of telebot.types.Chat:138 msgid ":class:`telebot.types.Chat`" msgstr "" @@ -1117,10 +1223,203 @@ msgid "" "reopen forum topics; supergroups only" msgstr "" -#: of telebot.types.ChatAdministratorRights:47 +#: of telebot.types.ChatAdministratorRights:46 +#: telebot.types.ChatMemberAdministrator:59 +msgid "Optional. True, if the administrator can post channel stories" +msgstr "" + +#: of telebot.types.ChatAdministratorRights:49 +#: telebot.types.ChatMemberAdministrator:62 +msgid "Optional. True, if the administrator can edit stories" +msgstr "" + +#: of telebot.types.ChatAdministratorRights:52 +#: telebot.types.ChatMemberAdministrator:65 +msgid "Optional. True, if the administrator can delete stories of other users" +msgstr "" + +#: of telebot.types.ChatAdministratorRights:56 msgid ":class:`telebot.types.ChatAdministratorRights`" msgstr "" +#: of telebot.types.ChatBoost:1 +msgid "This object contains information about a chat boost." +msgstr "" + +#: of telebot.types.ChatBoost:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#chatboost" +msgstr "" + +#: of telebot.types.ChatBoost:5 telebot.types.ChatBoostRemoved:8 +msgid "Unique identifier of the boost" +msgstr "" + +#: of telebot.types.ChatBoost:8 +msgid "Point in time (Unix timestamp) when the chat was boosted" +msgstr "" + +#: of telebot.types.ChatBoost:11 +msgid "" +"Point in time (Unix timestamp) when the boost will automatically expire, " +"unless the booster's Telegram Premium subscription is prolonged" +msgstr "" + +#: of telebot.types.ChatBoost:14 +msgid "Source of the added boost" +msgstr "" + +#: of telebot.types.ChatBoost:18 +msgid ":class:`ChatBoost`" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:1 +msgid "This object represents a boost removed from a chat." +msgstr "" + +#: of telebot.types.ChatBoostRemoved:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostremoved" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:5 telebot.types.ChatBoostUpdated:5 +msgid "Chat which was boosted" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:11 +msgid "Point in time (Unix timestamp) when the boost was removed" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:14 +msgid "Source of the removed boost" +msgstr "" + +#: of telebot.types.ChatBoostRemoved:18 +msgid ":class:`ChatBoostRemoved`" +msgstr "" + +#: of telebot.types.ChatBoostSource:1 +msgid "This object describes the source of a chat boost." +msgstr "" + +#: of telebot.types.ChatBoostSource:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#chatboostsource" +msgstr "" + +#: of telebot.types.ChatBoostSource:5 +msgid "Source of the boost" +msgstr "" + +#: of telebot.types.ChatBoostSource:9 +msgid ":class:`ChatBoostSource`" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:1 +#: telebot.types.ChatBoostSourceGiveaway:1 +#: telebot.types.ChatBoostSourcePremium:1 +msgid "Bases: :py:class:`telebot.types.ChatBoostSource`" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:1 +msgid "" +"The boost was obtained by the creation of Telegram Premium gift codes to " +"boost a chat." +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostsourcegiftcode" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:5 +msgid "Source of the boost, always “gift_code”" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:8 +msgid "User for which the gift code was created" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiftCode:12 +msgid ":class:`ChatBoostSourceGiftCode`" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:1 +msgid "The boost was obtained by the creation of a Telegram Premium giveaway." +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostsourcegiveaway" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:5 +msgid "Source of the boost, always “giveaway”" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:8 +msgid "" +"Identifier of a message in the chat with the giveaway; the message could " +"have been deleted already. May be 0 if the message isn't sent yet." +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:11 +msgid "User that won the prize in the giveaway if any" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:14 +msgid "" +"True, if the giveaway was completed, but there was no user to win the " +"prize" +msgstr "" + +#: of telebot.types.ChatBoostSourceGiveaway:18 +msgid ":class:`ChatBoostSourceGiveaway`" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:1 +msgid "" +"The boost was obtained by subscribing to Telegram Premium or by gifting a" +" Telegram Premium subscription to another user." +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostsourcepremium" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:5 +msgid "Source of the boost, always “premium”" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:8 +msgid "User that boosted the chat" +msgstr "" + +#: of telebot.types.ChatBoostSourcePremium:12 +msgid ":class:`ChatBoostSourcePremium`" +msgstr "" + +#: of telebot.types.ChatBoostUpdated:1 +msgid "This object represents a boost added to a chat or changed." +msgstr "" + +#: of telebot.types.ChatBoostUpdated:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#chatboostupdated" +msgstr "" + +#: of telebot.types.ChatBoostUpdated:8 +msgid "Infomation about the chat boost" +msgstr "" + +#: of telebot.types.ChatBoostUpdated:12 +msgid ":class:`ChatBoostUpdated`" +msgstr "" + #: of telebot.types.ChatInviteLink:1 msgid "Represents an invite link for a chat." msgstr "" @@ -1254,7 +1553,7 @@ msgstr "" msgid ":class:`telebot.types.ChatMemberOwner`" msgstr "" -#: of telebot.types.ChatMember:5 telebot.types.ChatMemberAdministrator:60 +#: of telebot.types.ChatMember:5 telebot.types.ChatMemberAdministrator:69 msgid ":class:`telebot.types.ChatMemberAdministrator`" msgstr "" @@ -1591,13 +1890,13 @@ msgid "" " defaults to the value of can_pin_messages" msgstr "" -#: of telebot.types.ChatPermissions:52 -msgid "" -"deprecated. True, if the user is allowed to send audios, documents, " -"photos, videos, video notes and voice notes" +#: of telebot.types.ChatPermissions:52 telebot.types.Message:27 +#: telebot.types.Message:30 telebot.types.Message:37 telebot.types.Message:40 +#: telebot.types.Message:43 +msgid "deprecated." msgstr "" -#: of telebot.types.ChatPermissions:57 +#: of telebot.types.ChatPermissions:56 msgid ":class:`telebot.types.ChatPermissions`" msgstr "" @@ -1650,7 +1949,7 @@ msgstr "" msgid "Telegram documentation: https://core.telegram.org/bots/api#Chatshared" msgstr "" -#: of telebot.types.ChatShared:6 telebot.types.UserShared:6 +#: of telebot.types.ChatShared:6 msgid "identifier of the request" msgstr "" @@ -1806,6 +2105,124 @@ msgstr "" msgid ":class:`telebot.types.Document`" msgstr "" +#: of telebot.types.ExternalReplyInfo:1 +msgid "" +"This object contains information about a message that is being replied " +"to, which may come from another chat or forum topic." +msgstr "" + +#: of telebot.types.ExternalReplyInfo:4 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#externalreplyinfo" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:6 +msgid "Origin of the message replied to by the given message" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:9 +msgid "" +"Optional. Chat the original message belongs to. Available only if the " +"chat is a supergroup or a channel." +msgstr "" + +#: of telebot.types.ExternalReplyInfo:12 +msgid "" +"Optional. Unique message identifier inside the original chat. Available " +"only if the original chat is a supergroup or a channel." +msgstr "" + +#: of telebot.types.ExternalReplyInfo:15 +msgid "" +"Optional. Options used for link preview generation for the original " +"message, if it is a text message" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:18 +msgid "Optional. Message is an animation, information about the animation" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:21 telebot.types.Message:97 +msgid "Optional. Message is an audio file, information about the file" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:24 telebot.types.Message:100 +msgid "Optional. Message is a general file, information about the file" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:27 telebot.types.Message:103 +msgid "Optional. Message is a photo, available sizes of the photo" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:30 telebot.types.Message:106 +msgid "Optional. Message is a sticker, information about the sticker" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:33 telebot.types.Message:109 +msgid "Optional. Message is a forwarded story" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:36 telebot.types.Message:112 +msgid "Optional. Message is a video, information about the video" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:39 telebot.types.Message:115 +msgid "Optional. Message is a video note, information about the video message" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:42 telebot.types.Message:118 +msgid "Optional. Message is a voice message, information about the file" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:45 telebot.types.Message:128 +msgid "Optional. True, if the message media is covered by a spoiler animation" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:48 telebot.types.Message:131 +msgid "Optional. Message is a shared contact, information about the contact" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:51 telebot.types.Message:134 +msgid "Optional. Message is a dice with random value" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:54 telebot.types.Message:137 +msgid "" +"Optional. Message is a game, information about the game. More about games" +" »" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:57 +msgid "Optional. Message is a scheduled giveaway, information about the giveaway" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:60 +msgid "Optional. A giveaway with public winners was completed" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:63 telebot.types.Message:200 +msgid "" +"Optional. Message is an invoice for a payment, information about the " +"invoice. More about payments »" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:66 telebot.types.Message:147 +msgid "Optional. Message is a shared location, information about the location" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:69 telebot.types.Message:140 +msgid "Optional. Message is a native poll, information about the poll" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:72 +msgid "Optional. Message is a venue, information about the venue" +msgstr "" + +#: of telebot.types.ExternalReplyInfo:76 +msgid ":class:`ExternalReplyInfo`" +msgstr "" + #: of telebot.types.File:1 msgid "" "This object represents a file ready to be downloaded. The file can be " @@ -2061,33 +2478,209 @@ msgid "" "https://core.telegram.org/bots/api#generalforumtopicunhidden" msgstr "" -#: of telebot.types.InlineKeyboardButton:1 telebot.types.InlineKeyboardMarkup:1 -#: telebot.types.LoginUrl:1 telebot.types.MessageEntity:1 -msgid "" -"Bases: :py:class:`telebot.types.Dictionaryable`, " -":py:class:`telebot.types.JsonSerializable`, " -":py:class:`telebot.types.JsonDeserializable`" +#: of telebot.types.Giveaway:1 +msgid "This object represents a message about a scheduled giveaway." msgstr "" -#: of telebot.types.InlineKeyboardButton:1 -msgid "" -"This object represents one button of an inline keyboard. You must use " -"exactly one of the optional fields." +#: of telebot.types.Giveaway:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#giveaway" msgstr "" -#: of telebot.types.InlineKeyboardButton:3 -#: telebot.types.SwitchInlineQueryChosenChat:4 -msgid "" -"Telegram Documentation: " -"https://core.telegram.org/bots/api#inlinekeyboardbutton" +#: of telebot.types.Giveaway:5 +msgid "The list of chats which the user must join to participate in the giveaway" msgstr "" -#: of telebot.types.InlineKeyboardButton:5 -#: telebot.types.InlineQueryResultsButton:6 -msgid "Label text on the button" +#: of telebot.types.Giveaway:8 +msgid "" +"Point in time (Unix timestamp) when winners of the giveaway will be " +"selected" msgstr "" -#: of telebot.types.InlineKeyboardButton:8 +#: of telebot.types.Giveaway:11 +msgid "" +"The number of users which are supposed to be selected as winners of the " +"giveaway" +msgstr "" + +#: of telebot.types.Giveaway:14 +msgid "" +"Optional. True, if only users who join the chats after the giveaway " +"started should be eligible to win" +msgstr "" + +#: of telebot.types.Giveaway:17 +msgid "" +"Optional. True, if the list of giveaway winners will be visible to " +"everyone" +msgstr "" + +#: of telebot.types.Giveaway:20 telebot.types.GiveawayWinners:35 +msgid "Optional. Description of additional giveaway prize" +msgstr "" + +#: of telebot.types.Giveaway:23 +msgid "" +"Optional. A list of two-letter ISO 3166-1 alpha-2 country codes " +"indicating the countries from which eligible users for the giveaway must " +"come. If empty, then all users can participate in the giveaway." +msgstr "" + +#: of telebot.types.Giveaway:26 telebot.types.GiveawayWinners:23 +msgid "" +"Optional. The number of months the Telegram Premium subscription won from" +" the giveaway will be active for" +msgstr "" + +#: of telebot.types.Giveaway:30 +msgid ":class:`Giveaway`" +msgstr "" + +#: of telebot.types.GiveawayCompleted:1 +msgid "" +"This object represents a service message about the completion of a " +"giveaway without public winners." +msgstr "" + +#: of telebot.types.GiveawayCompleted:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#giveawaycompleted" +msgstr "" + +#: of telebot.types.GiveawayCompleted:5 +msgid "Number of winners in the giveaway" +msgstr "" + +#: of telebot.types.GiveawayCompleted:8 telebot.types.GiveawayWinners:26 +msgid "Optional. Number of undistributed prizes" +msgstr "" + +#: of telebot.types.GiveawayCompleted:11 +msgid "" +"Optional. Message with the giveaway that was completed, if it wasn't " +"deleted" +msgstr "" + +#: of telebot.types.GiveawayCompleted:15 +msgid ":class:`GiveawayCompleted`" +msgstr "" + +#: of telebot.types.GiveawayCreated:1 +msgid "" +"This object represents a service message about the creation of a " +"scheduled giveaway. Currently holds no information." +msgstr "" + +#: of telebot.types.GiveawayWinners:1 +msgid "" +"This object represents a message about the completion of a giveaway with " +"public winners." +msgstr "" + +#: of telebot.types.GiveawayWinners:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#giveawaywinners" +msgstr "" + +#: of telebot.types.GiveawayWinners:5 +msgid "The chat that created the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:8 +msgid "Identifier of the messsage with the giveaway in the chat" +msgstr "" + +#: of telebot.types.GiveawayWinners:11 +msgid "Point in time (Unix timestamp) when winners of the giveaway were selected" +msgstr "" + +#: of telebot.types.GiveawayWinners:14 +msgid "Total number of winners in the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:17 +msgid "List of up to 100 winners of the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:20 +msgid "" +"Optional. The number of other chats the user had to join in order to be " +"eligible for the giveaway" +msgstr "" + +#: of telebot.types.GiveawayWinners:29 +msgid "" +"Optional. True, if only users who had joined the chats after the giveaway" +" started were eligible to win" +msgstr "" + +#: of telebot.types.GiveawayWinners:32 +msgid "" +"Optional. True, if the giveaway was canceled because the payment for it " +"was refunded" +msgstr "" + +#: of telebot.types.GiveawayWinners:39 +msgid ":class:`GiveawayWinners`" +msgstr "" + +#: of telebot.types.InaccessibleMessage:1 +msgid "" +"This object describes a message that was deleted or is otherwise " +"inaccessible to the bot." +msgstr "" + +#: of telebot.types.InaccessibleMessage:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#inaccessiblemessage" +msgstr "" + +#: of telebot.types.InaccessibleMessage:5 +msgid "Chat the message belonged to" +msgstr "" + +#: of telebot.types.InaccessibleMessage:8 telebot.types.MessageOriginChannel:6 +#: telebot.types.MessageReactionCountUpdated:8 +msgid "Unique message identifier inside the chat" +msgstr "" + +#: of telebot.types.InaccessibleMessage:11 +msgid "" +"Always 0. The field can be used to differentiate regular and inaccessible" +" messages." +msgstr "" + +#: of telebot.types.InaccessibleMessage:15 +msgid ":class:`InaccessibleMessage`" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:1 telebot.types.InlineKeyboardMarkup:1 +#: telebot.types.LoginUrl:1 telebot.types.MessageEntity:1 +msgid "" +"Bases: :py:class:`telebot.types.Dictionaryable`, " +":py:class:`telebot.types.JsonSerializable`, " +":py:class:`telebot.types.JsonDeserializable`" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:1 +msgid "" +"This object represents one button of an inline keyboard. You must use " +"exactly one of the optional fields." +msgstr "" + +#: of telebot.types.InlineKeyboardButton:3 +#: telebot.types.SwitchInlineQueryChosenChat:4 +msgid "" +"Telegram Documentation: " +"https://core.telegram.org/bots/api#inlinekeyboardbutton" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:5 +#: telebot.types.InlineQueryResultsButton:6 +msgid "Label text on the button" +msgstr "" + +#: of telebot.types.InlineKeyboardButton:8 msgid "" "Optional. HTTP or tg:// URL to be opened when the button is pressed. " "Links tg://user?id= can be used to mention a user by their ID " @@ -3390,7 +3983,7 @@ msgstr "" #: telebot.types.InputVenueMessageContent:1 #: telebot.types.KeyboardButtonPollType:1 #: telebot.types.KeyboardButtonRequestChat:1 -#: telebot.types.KeyboardButtonRequestUser:1 +#: telebot.types.KeyboardButtonRequestUsers:1 msgid "Bases: :py:class:`telebot.types.Dictionaryable`" msgstr "" @@ -3842,11 +4435,16 @@ msgid "" " be specified instead of parse_mode" msgstr "" -#: of telebot.types.InputTextMessageContent:16 -msgid "Optional. Disables link previews for links in the sent message" +#: of telebot.types.InputTextMessageContent:16 telebot.types.KeyboardButton:25 +#: telebot.types.StickerSet:20 +msgid "deprecated" +msgstr "" + +#: of telebot.types.InputTextMessageContent:19 +msgid "Optional. Link preview generation options for the message" msgstr "" -#: of telebot.types.InputTextMessageContent:20 +#: of telebot.types.InputTextMessageContent:23 msgid ":class:`telebot.types.InputTextMessageContent`" msgstr "" @@ -3980,21 +4578,21 @@ msgid "" "service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:25 +#: of telebot.types.KeyboardButton:28 msgid "" "Optional. If specified, pressing the button will open a list of suitable " -"users. Tapping on any user will send their identifier to the bot in a " -"“user_shared” service message. Available in private chats only." +"users. Identifiers of selected users will be sent to the bot in a " +"“users_shared” service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:29 +#: of telebot.types.KeyboardButton:32 msgid "" "Optional. If specified, pressing the button will open a list of suitable " "chats. Tapping on a chat will send its identifier to the bot in a " "“chat_shared” service message. Available in private chats only." msgstr "" -#: of telebot.types.KeyboardButton:34 +#: of telebot.types.KeyboardButton:37 msgid ":class:`telebot.types.KeyboardButton`" msgstr "" @@ -4094,39 +4692,51 @@ msgid ":class:`telebot.types.KeyboardButtonRequestChat`" msgstr "" #: of telebot.types.KeyboardButtonRequestUser:1 +msgid "Bases: :py:class:`telebot.types.KeyboardButtonRequestUsers`" +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUser:1 +msgid "Deprecated. Use KeyboardButtonRequestUsers instead." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUsers:1 msgid "" "This object defines the criteria used to request a suitable user. The " "identifier of the selected user will be shared with the bot when the " "corresponding button is pressed." msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:4 +#: of telebot.types.KeyboardButtonRequestUsers:4 msgid "" "Telegram documentation: " -"https://core.telegram.org/bots/api#keyboardbuttonrequestuser" +"https://core.telegram.org/bots/api#keyboardbuttonrequestusers" msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:6 +#: of telebot.types.KeyboardButtonRequestUsers:6 msgid "" "Signed 32-bit identifier of the request, which will be received back in " -"the UserShared object. Must be unique within the message" +"the UsersShared object. Must be unique within the message" msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:10 +#: of telebot.types.KeyboardButtonRequestUsers:10 msgid "" "Optional. Pass True to request a bot, pass False to request a regular " "user. If not specified, no additional restrictions are applied." msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:14 +#: of telebot.types.KeyboardButtonRequestUsers:14 msgid "" "Optional. Pass True to request a premium user, pass False to request a " "non-premium user. If not specified, no additional restrictions are " "applied." msgstr "" -#: of telebot.types.KeyboardButtonRequestUser:19 -msgid ":class:`telebot.types.KeyboardButtonRequestUser`" +#: of telebot.types.KeyboardButtonRequestUsers:18 +msgid "Optional. The maximum number of users to be selected; 1-10. Defaults to 1." +msgstr "" + +#: of telebot.types.KeyboardButtonRequestUsers:22 +msgid ":class:`telebot.types.KeyboardButtonRequestUsers`" msgstr "" #: of telebot.types.LabeledPrice:1 @@ -4154,6 +4764,59 @@ msgstr "" msgid ":class:`telebot.types.LabeledPrice`" msgstr "" +#: of telebot.types.LinkPreviewOptions:1 telebot.types.ReactionType:1 +#: telebot.types.ReplyParameters:1 telebot.types.SwitchInlineQueryChosenChat:1 +#: telebot.types.User:1 +msgid "" +"Bases: :py:class:`telebot.types.JsonDeserializable`, " +":py:class:`telebot.types.Dictionaryable`, " +":py:class:`telebot.types.JsonSerializable`" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:1 +msgid "Describes the options used for link preview generation." +msgstr "" + +#: of telebot.types.LinkPreviewOptions:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#linkpreviewoptions" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:5 +msgid "Optional. True, if the link preview is disabled" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:8 +msgid "" +"Optional. URL to use for the link preview. If empty, then the first URL " +"found in the message text will be used" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:11 +msgid "" +"Optional. True, if the media in the link preview is supposed to be " +"shrunk; ignored if the URL isn't explicitly specified or media size " +"change isn't supported for the preview" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:14 +msgid "" +"Optional. True, if the media in the link preview is supposed to be " +"enlarged; ignored if the URL isn't explicitly specified or media size " +"change isn't supported for the preview" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:17 +msgid "" +"Optional. True, if the link preview must be shown above the message text;" +" otherwise, the link preview will be shown below the message text" +msgstr "" + +#: of telebot.types.LinkPreviewOptions:21 +msgid ":class:`LinkPreviewOptions`" +msgstr "" + #: of telebot.types.Location:1 msgid "This object represents a point on the map." msgstr "" @@ -4421,39 +5084,8 @@ msgstr "" msgid "Conversation the message belongs to" msgstr "" -#: of telebot.types.Message:27 -msgid "Optional. For forwarded messages, sender of the original message" -msgstr "" - -#: of telebot.types.Message:30 -msgid "" -"Optional. For messages forwarded from channels or from anonymous " -"administrators, information about the original sender chat" -msgstr "" - -#: of telebot.types.Message:34 -msgid "" -"Optional. For messages forwarded from channels, identifier of the " -"original message in the channel" -msgstr "" - -#: of telebot.types.Message:38 -msgid "" -"Optional. For forwarded messages that were originally sent in channels or" -" by an anonymous chat administrator, signature of the message sender if " -"present" -msgstr "" - -#: of telebot.types.Message:42 -msgid "" -"Optional. Sender's name for messages forwarded from users who disallow " -"adding a link to their account in forwarded messages" -msgstr "" - -#: of telebot.types.Message:46 -msgid "" -"Optional. For forwarded messages, date the original message was sent in " -"Unix time" +#: of telebot.types.Message:33 +msgid "deprecated. message in the channel" msgstr "" #: of telebot.types.Message:49 @@ -4474,148 +5106,112 @@ msgid "" msgstr "" #: of telebot.types.Message:60 -msgid "Optional. Bot through which the message was sent" +msgid "" +"Optional. Information about the message that is being replied to, which " +"may come from another chat or forum topic" msgstr "" #: of telebot.types.Message:63 -msgid "Optional. Date the message was last edited in Unix time" +msgid "" +"Optional. For replies that quote part of the original message, the quoted" +" part of the message" msgstr "" #: of telebot.types.Message:66 -msgid "Optional. :obj:`bool`, if the message can't be forwarded" +msgid "Optional. Bot through which the message was sent" msgstr "" #: of telebot.types.Message:69 +msgid "Optional. Date the message was last edited in Unix time" +msgstr "" + +#: of telebot.types.Message:72 +msgid "Optional. :obj:`bool`, if the message can't be forwarded" +msgstr "" + +#: of telebot.types.Message:75 msgid "" "Optional. The unique identifier of a media message group this message " "belongs to" msgstr "" -#: of telebot.types.Message:72 +#: of telebot.types.Message:78 msgid "" "Optional. Signature of the post author for messages in channels, or the " "custom title of an anonymous group administrator" msgstr "" -#: of telebot.types.Message:76 +#: of telebot.types.Message:82 msgid "Optional. For text messages, the actual UTF-8 text of the message" msgstr "" -#: of telebot.types.Message:79 +#: of telebot.types.Message:85 msgid "" "Optional. For text messages, special entities like usernames, URLs, bot " "commands, etc. that appear in the text" msgstr "" -#: of telebot.types.Message:83 +#: of telebot.types.Message:89 msgid "" -"Optional. Message is an animation, information about the animation. For " -"backward compatibility, when this field is set, the document field will " -"also be set" -msgstr "" - -#: of telebot.types.Message:87 -msgid "Optional. Message is an audio file, information about the file" -msgstr "" - -#: of telebot.types.Message:90 -msgid "Optional. Message is a general file, information about the file" +"Optional. Options used for link preview generation for the message, if it" +" is a text message and link preview options were changed" msgstr "" #: of telebot.types.Message:93 -msgid "Optional. Message is a photo, available sizes of the photo" -msgstr "" - -#: of telebot.types.Message:96 -msgid "Optional. Message is a sticker, information about the sticker" -msgstr "" - -#: of telebot.types.Message:99 -msgid "Optional. Message is a video, information about the video" -msgstr "" - -#: of telebot.types.Message:102 -msgid "Optional. Message is a video note, information about the video message" -msgstr "" - -#: of telebot.types.Message:105 -msgid "Optional. Message is a voice message, information about the file" +msgid "" +"Optional. Message is an animation, information about the animation. For " +"backward compatibility, when this field is set, the document field will " +"also be set" msgstr "" -#: of telebot.types.Message:108 +#: of telebot.types.Message:121 msgid "" "Optional. Caption for the animation, audio, document, photo, video or " "voice" msgstr "" -#: of telebot.types.Message:111 +#: of telebot.types.Message:124 msgid "" "Optional. For messages with a caption, special entities like usernames, " "URLs, bot commands, etc. that appear in the caption" msgstr "" -#: of telebot.types.Message:115 -msgid "Optional. True, if the message media is covered by a spoiler animation" -msgstr "" - -#: of telebot.types.Message:118 -msgid "Optional. Message is a shared contact, information about the contact" -msgstr "" - -#: of telebot.types.Message:121 -msgid "Optional. Message is a dice with random value" -msgstr "" - -#: of telebot.types.Message:124 -msgid "" -"Optional. Message is a game, information about the game. More about games" -" »" -msgstr "" - -#: of telebot.types.Message:127 -msgid "Optional. Message is a native poll, information about the poll" -msgstr "" - -#: of telebot.types.Message:130 +#: of telebot.types.Message:143 msgid "" "Optional. Message is a venue, information about the venue. For backward " "compatibility, when this field is set, the location field will also be " "set" msgstr "" -#: of telebot.types.Message:134 -msgid "Optional. Message is a shared location, information about the location" -msgstr "" - -#: of telebot.types.Message:137 +#: of telebot.types.Message:150 msgid "" "Optional. New members that were added to the group or supergroup and " "information about them (the bot itself may be one of these members)" msgstr "" -#: of telebot.types.Message:141 +#: of telebot.types.Message:154 msgid "" "Optional. A member was removed from the group, information about them " "(this member may be the bot itself)" msgstr "" -#: of telebot.types.Message:145 +#: of telebot.types.Message:158 msgid "Optional. A chat title was changed to this value" msgstr "" -#: of telebot.types.Message:148 +#: of telebot.types.Message:161 msgid "Optional. A chat photo was change to this value" msgstr "" -#: of telebot.types.Message:151 +#: of telebot.types.Message:164 msgid "Optional. Service message: the chat photo was deleted" msgstr "" -#: of telebot.types.Message:154 +#: of telebot.types.Message:167 msgid "Optional. Service message: the group has been created" msgstr "" -#: of telebot.types.Message:157 +#: of telebot.types.Message:170 msgid "" "Optional. Service message: the supergroup has been created. This field " "can't be received in a message coming through updates, because bot can't " @@ -4624,7 +5220,7 @@ msgid "" " created supergroup." msgstr "" -#: of telebot.types.Message:162 +#: of telebot.types.Message:175 msgid "" "Optional. Service message: the channel has been created. This field can't" " be received in a message coming through updates, because bot can't be a " @@ -4632,11 +5228,11 @@ msgid "" "reply_to_message if someone replies to a very first message in a channel." msgstr "" -#: of telebot.types.Message:167 +#: of telebot.types.Message:180 msgid "Optional. Service message: auto-delete timer settings changed in the chat" msgstr "" -#: of telebot.types.Message:171 +#: of telebot.types.Message:184 msgid "" "Optional. The group has been migrated to a supergroup with the specified " "identifier. This number may have more than 32 significant bits and some " @@ -4645,7 +5241,7 @@ msgid "" " double-precision float type are safe for storing this identifier." msgstr "" -#: of telebot.types.Message:177 +#: of telebot.types.Message:190 msgid "" "Optional. The supergroup has been migrated from a group with the " "specified identifier. This number may have more than 32 significant bits " @@ -4655,106 +5251,124 @@ msgid "" "identifier." msgstr "" -#: of telebot.types.Message:183 +#: of telebot.types.Message:196 msgid "" "Optional. Specified message was pinned. Note that the Message object in " "this field will not contain further reply_to_message fields even if it is" " itself a reply." msgstr "" -#: of telebot.types.Message:187 -msgid "" -"Optional. Message is an invoice for a payment, information about the " -"invoice. More about payments »" -msgstr "" - -#: of telebot.types.Message:190 +#: of telebot.types.Message:203 msgid "" "Optional. Message is a service message about a successful payment, " "information about the payment. More about payments »" msgstr "" -#: of telebot.types.Message:194 +#: of telebot.types.Message:207 msgid "Optional. Service message: a user was shared with the bot" msgstr "" -#: of telebot.types.Message:197 +#: of telebot.types.Message:210 msgid "Optional. Service message: a chat was shared with the bot" msgstr "" -#: of telebot.types.Message:200 +#: of telebot.types.Message:213 msgid "" "Optional. The domain name of the website on which the user has logged in." " More about Telegram Login »" msgstr "" -#: of telebot.types.Message:204 +#: of telebot.types.Message:217 msgid "" "Optional. Service message: the user allowed the bot added to the " "attachment menu to write messages" msgstr "" -#: of telebot.types.Message:208 +#: of telebot.types.Message:221 msgid "Optional. Telegram Passport data" msgstr "" -#: of telebot.types.Message:211 +#: of telebot.types.Message:224 msgid "" "Optional. Service message. A user in the chat triggered another user's " "proximity alert while sharing Live Location." msgstr "" -#: of telebot.types.Message:215 +#: of telebot.types.Message:228 msgid "Optional. Service message: forum topic created" msgstr "" -#: of telebot.types.Message:218 +#: of telebot.types.Message:231 msgid "Optional. Service message: forum topic edited" msgstr "" -#: of telebot.types.Message:221 +#: of telebot.types.Message:234 msgid "Optional. Service message: forum topic closed" msgstr "" -#: of telebot.types.Message:224 +#: of telebot.types.Message:237 msgid "Optional. Service message: forum topic reopened" msgstr "" -#: of telebot.types.Message:227 +#: of telebot.types.Message:240 msgid "Optional. Service message: the 'General' forum topic hidden" msgstr "" -#: of telebot.types.Message:230 +#: of telebot.types.Message:243 msgid "Optional. Service message: the 'General' forum topic unhidden" msgstr "" -#: of telebot.types.Message:233 +#: of telebot.types.Message:246 +msgid "Optional. Service message: a giveaway has been created" +msgstr "" + +#: of telebot.types.Message:249 +msgid "Optional. The message is a scheduled giveaway message" +msgstr "" + +#: of telebot.types.Message:252 +msgid "Optional. Service message: giveaway winners(public winners)" +msgstr "" + +#: of telebot.types.Message:255 +msgid "Optional. Service message: giveaway completed, without public winners" +msgstr "" + +#: of telebot.types.Message:258 msgid "Optional. Service message: video chat scheduled" msgstr "" -#: of telebot.types.Message:236 +#: of telebot.types.Message:261 msgid "Optional. Service message: video chat started" msgstr "" -#: of telebot.types.Message:239 +#: of telebot.types.Message:264 msgid "Optional. Service message: video chat ended" msgstr "" -#: of telebot.types.Message:242 +#: of telebot.types.Message:267 msgid "Optional. Service message: new participants invited to a video chat" msgstr "" -#: of telebot.types.Message:245 +#: of telebot.types.Message:270 msgid "Optional. Service message: data sent by a Web App" msgstr "" -#: of telebot.types.Message:248 +#: of telebot.types.Message:273 msgid "" "Optional. Inline keyboard attached to the message. login_url buttons are " "represented as ordinary url buttons." msgstr "" -#: of telebot.types.Message:253 +#: of telebot.types.Message +msgid "forward_origin" +msgstr "" + +#: of telebot.types.Message:46 +msgid "Optional. For forwarded messages, information about the original message;" +msgstr "" + +#: of telebot.types.Message:278 msgid ":class:`telebot.types.Message`" msgstr "" @@ -4873,12 +5487,163 @@ msgstr "" msgid ":class:`telebot.types.MessageId`" msgstr "" -#: of telebot.types.OrderInfo:1 -msgid "This object represents information about an order." +#: of telebot.types.MessageOrigin:1 +msgid "This object describes the origin of a message." msgstr "" -#: of telebot.types.OrderInfo:3 -msgid "Telegram Documentation: https://core.telegram.org/bots/api#orderinfo" +#: of telebot.types.MessageOrigin:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#messageorigin" +msgstr "" + +#: of telebot.types.MessageOrigin:5 +msgid "Type of the message origin" +msgstr "" + +#: of telebot.types.MessageOrigin:8 +msgid "Date the message was sent originally in Unix time" +msgstr "" + +#: of telebot.types.MessageOrigin:11 +msgid "User that sent the message originally (for MessageOriginUser)" +msgstr "" + +#: of telebot.types.MessageOrigin:14 +msgid "" +"Name of the user that sent the message originally (for " +"MessageOriginHiddenUser)" +msgstr "" + +#: of telebot.types.MessageOrigin:17 +msgid "Chat that sent the message originally (for MessageOriginChat)" +msgstr "" + +#: of telebot.types.MessageOrigin:20 +msgid "Optional. Author signature for certain cases" +msgstr "" + +#: of telebot.types.MessageOrigin:24 +msgid ":class:`MessageOrigin`" +msgstr "" + +#: of telebot.types.MessageOriginChannel:1 telebot.types.MessageOriginChat:1 +#: telebot.types.MessageOriginHiddenUser:1 telebot.types.MessageOriginUser:1 +msgid "Bases: :py:class:`telebot.types.MessageOrigin`" +msgstr "" + +#: of telebot.types.MessageOriginChannel:1 +msgid "The message was originally sent to a channel chat." +msgstr "" + +#: of telebot.types.MessageOriginChannel:3 +msgid "Channel chat to which the message was originally sent" +msgstr "" + +#: of telebot.types.MessageOriginChannel:9 +msgid "Optional. Signature of the original post author" +msgstr "" + +#: of telebot.types.MessageOriginChat:1 +msgid "The message was originally sent on behalf of a chat to a group chat." +msgstr "" + +#: of telebot.types.MessageOriginChat:3 +msgid "Chat that sent the message originally" +msgstr "" + +#: of telebot.types.MessageOriginChat:6 +msgid "" +"Optional. For messages originally sent by an anonymous chat " +"administrator, original message author signature" +msgstr "" + +#: of telebot.types.MessageOriginHiddenUser:1 +msgid "The message was originally sent by an unknown user." +msgstr "" + +#: of telebot.types.MessageOriginHiddenUser:3 +msgid "Name of the user that sent the message originally" +msgstr "" + +#: of telebot.types.MessageOriginUser:1 +msgid "The message was originally sent by a known user." +msgstr "" + +#: of telebot.types.MessageOriginUser:3 +msgid "User that sent the message originally" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:1 +#: telebot.types.MessageReactionUpdated:1 +msgid "" +"This object represents a service message about a change in the list of " +"the current user's reactions to a message." +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#messagereactioncountupdated" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:5 +msgid "The chat containing the message" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:11 +#: telebot.types.MessageReactionUpdated:17 +msgid "Date of the change in Unix time" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:14 +msgid "List of reactions that are present on the message" +msgstr "" + +#: of telebot.types.MessageReactionCountUpdated:18 +msgid ":class:`MessageReactionCountUpdated`" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#messagereactionupdated" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:5 +msgid "The chat containing the message the user reacted to" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:8 +msgid "Unique identifier of the message inside the chat" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:11 +msgid "Optional. The user that changed the reaction, if the user isn't anonymous" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:14 +msgid "" +"Optional. The chat on behalf of which the reaction was changed, if the " +"user is anonymous" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:20 +msgid "Previous list of reaction types that were set by the user" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:23 +msgid "New list of reaction types that have been set by the user" +msgstr "" + +#: of telebot.types.MessageReactionUpdated:27 +msgid ":class:`MessageReactionUpdated`" +msgstr "" + +#: of telebot.types.OrderInfo:1 +msgid "This object represents information about an order." +msgstr "" + +#: of telebot.types.OrderInfo:3 +msgid "Telegram Documentation: https://core.telegram.org/bots/api#orderinfo" msgstr "" #: of telebot.types.OrderInfo:5 @@ -5016,16 +5781,22 @@ msgid "Telegram Documentation: https://core.telegram.org/bots/api#pollanswer" msgstr "" #: of telebot.types.PollAnswer:8 -msgid "The user, who changed the answer to the poll" +msgid "" +"Optional. The chat that changed the answer to the poll, if the voter is " +"anonymous" msgstr "" #: of telebot.types.PollAnswer:11 +msgid "Optional. The user, who changed the answer to the poll" +msgstr "" + +#: of telebot.types.PollAnswer:14 msgid "" "0-based identifiers of answer options, chosen by the user. May be empty " "if the user retracted their vote." msgstr "" -#: of telebot.types.PollAnswer:16 +#: of telebot.types.PollAnswer:19 msgid ":class:`telebot.types.PollAnswer`" msgstr "" @@ -5112,6 +5883,88 @@ msgstr "" msgid ":class:`telebot.types.ProximityAlertTriggered`" msgstr "" +#: of telebot.types.ReactionCount:1 +msgid "" +"This object represents a reaction added to a message along with the " +"number of times it was added." +msgstr "" + +#: of telebot.types.ReactionCount:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#reactioncount" +msgstr "" + +#: of telebot.types.ReactionCount:5 telebot.types.ReactionType:5 +msgid "Type of the reaction" +msgstr "" + +#: of telebot.types.ReactionCount:8 +msgid "Number of times the reaction was added" +msgstr "" + +#: of telebot.types.ReactionCount:12 +msgid ":class:`ReactionCount`" +msgstr "" + +#: of telebot.types.ReactionType:1 +msgid "This object represents a reaction type." +msgstr "" + +#: of telebot.types.ReactionType:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#reactiontype" +msgstr "" + +#: of telebot.types.ReactionType:9 +msgid ":class:`ReactionType`" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:1 telebot.types.ReactionTypeEmoji:1 +msgid "Bases: :py:class:`telebot.types.ReactionType`" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:1 +msgid "This object represents a custom emoji reaction type." +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#reactiontypecustomemoji" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:5 +msgid "Type of the reaction, must be custom_emoji" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:8 +msgid "Identifier of the custom emoji" +msgstr "" + +#: of telebot.types.ReactionTypeCustomEmoji:12 +msgid ":class:`ReactionTypeCustomEmoji`" +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:1 +msgid "This object represents an emoji reaction type." +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:3 +msgid "" +"Telegram documentation: " +"https://core.telegram.org/bots/api#reactiontypeemoji" +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:5 +msgid "Type of the reaction, must be emoji" +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:8 +msgid "Reaction emoji. List is available on the API doc." +msgstr "" + +#: of telebot.types.ReactionTypeEmoji:12 +msgid ":class:`ReactionTypeEmoji`" +msgstr "" + #: of telebot.types.ReplyKeyboardMarkup:1 msgid "" "This object represents a custom keyboard with reply options (see " @@ -5265,6 +6118,65 @@ msgstr "" msgid ":class:`telebot.types.ReplyKeyboardRemove`" msgstr "" +#: of telebot.types.ReplyParameters:1 +msgid "Describes reply parameters for the message that is being sent." +msgstr "" + +#: of telebot.types.ReplyParameters:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#replyparameters" +msgstr "" + +#: of telebot.types.ReplyParameters:5 +msgid "" +"Identifier of the message that will be replied to in the current chat, or" +" in the chat chat_id if it is specified" +msgstr "" + +#: of telebot.types.ReplyParameters:8 +msgid "" +"Optional. If the message to be replied to is from a different chat, " +"unique identifier for the chat or username of the channel (in the format " +"@channelusername)" +msgstr "" + +#: of telebot.types.ReplyParameters:11 +msgid "" +"Optional. Pass True if the message should be sent even if the specified " +"message to be replied to is not found; can be used only for replies in " +"the same chat and forum topic." +msgstr "" + +#: of telebot.types.ReplyParameters:14 +msgid "" +"Optional. Quoted part of the message to be replied to; 0-1024 characters " +"after entities parsing. The quote must be an exact substring of the " +"message to be replied to, including bold, italic, underline, " +"strikethrough, spoiler, and custom_emoji entities. The message will fail " +"to send if the quote isn't found in the original message." +msgstr "" + +#: of telebot.types.ReplyParameters:17 +msgid "" +"Optional. Mode for parsing entities in the quote. See formatting options " +"for more details." +msgstr "" + +#: of telebot.types.ReplyParameters:20 +msgid "" +"Optional. A JSON-serialized list of special entities that appear in the " +"quote. It can be specified instead of quote_parse_mode." +msgstr "" + +#: of telebot.types.ReplyParameters:23 +msgid "" +"Optional. Position of the quote in the original message in UTF-16 code " +"units" +msgstr "" + +#: of telebot.types.ReplyParameters:27 +msgid ":class:`ReplyParameters`" +msgstr "" + #: of telebot.types.SentWebAppMessage:1 telebot.types.WebAppData:1 #: telebot.types.WebAppInfo:1 msgid "" @@ -5476,21 +6388,15 @@ msgstr "" msgid "True, if the sticker set contains video stickers" msgstr "" -#: of telebot.types.StickerSet:20 -msgid "" -"True, if the sticker set contains masks. Deprecated since Bot API 6.2, " -"use sticker_type instead." -msgstr "" - -#: of telebot.types.StickerSet:24 +#: of telebot.types.StickerSet:23 msgid "List of all set stickers" msgstr "" -#: of telebot.types.StickerSet:27 +#: of telebot.types.StickerSet:26 msgid "Optional. Sticker set thumbnail in the .WEBP, .TGS, or .WEBM format" msgstr "" -#: of telebot.types.StickerSet:31 +#: of telebot.types.StickerSet:30 msgid ":class:`telebot.types.StickerSet`" msgstr "" @@ -5498,6 +6404,12 @@ msgstr "" msgid "Deprecated since Bot API 6.2, use sticker_type instead." msgstr "" +#: of telebot.types.Story:1 +msgid "" +"This object represents a message about a forwarded story in the chat. " +"Currently holds no information." +msgstr "" + #: of telebot.types.SuccessfulPayment:1 msgid "This object contains basic information about a successful payment." msgstr "" @@ -5520,13 +6432,6 @@ msgstr "" msgid ":class:`telebot.types.SuccessfulPayment`" msgstr "" -#: of telebot.types.SwitchInlineQueryChosenChat:1 telebot.types.User:1 -msgid "" -"Bases: :py:class:`telebot.types.JsonDeserializable`, " -":py:class:`telebot.types.Dictionaryable`, " -":py:class:`telebot.types.JsonSerializable`" -msgstr "" - #: of telebot.types.SwitchInlineQueryChosenChat:1 msgid "" "Represents an inline button that switches the current user to inline mode" @@ -5559,6 +6464,45 @@ msgstr "" msgid ":class:`SwitchInlineQueryChosenChat`" msgstr "" +#: of telebot.types.TextQuote:1 +msgid "" +"This object contains information about the quoted part of a message that " +"is replied to by the given message." +msgstr "" + +#: of telebot.types.TextQuote:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#textquote" +msgstr "" + +#: of telebot.types.TextQuote:5 +msgid "" +"Text of the quoted part of a message that is replied to by the given " +"message" +msgstr "" + +#: of telebot.types.TextQuote:8 +msgid "" +"Optional. Special entities that appear in the quote. Currently, only " +"bold, italic, underline, strikethrough, spoiler, and custom_emoji " +"entities are kept in quotes." +msgstr "" + +#: of telebot.types.TextQuote:11 +msgid "" +"Approximate quote position in the original message in UTF-16 code units " +"as specified by the sender" +msgstr "" + +#: of telebot.types.TextQuote:14 +msgid "" +"Optional. True, if the quote was chosen manually by the message sender. " +"Otherwise, the quote was added automatically by the server." +msgstr "" + +#: of telebot.types.TextQuote:18 +msgid ":class:`TextQuote`" +msgstr "" + #: of telebot.types.Update:1 msgid "" "This object represents an incoming update.At most one of the optional " @@ -5600,66 +6544,94 @@ msgid "" msgstr "" #: of telebot.types.Update:23 +msgid "" +"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." +msgstr "" + +#: of telebot.types.Update:27 +msgid "" +"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." +msgstr "" + +#: of telebot.types.Update:31 msgid "Optional. New incoming inline query" msgstr "" -#: of telebot.types.Update:26 +#: of telebot.types.Update:34 msgid "" "Optional. The result of an inline query that was chosen by a user and " "sent to their chat partner. Please see our documentation on the feedback " "collecting for details on how to enable these updates for your bot." msgstr "" -#: of telebot.types.Update:31 +#: of telebot.types.Update:39 msgid "Optional. New incoming callback query" msgstr "" -#: of telebot.types.Update:34 +#: of telebot.types.Update:42 msgid "" "Optional. New incoming shipping query. Only for invoices with flexible " "price" msgstr "" -#: of telebot.types.Update:37 +#: of telebot.types.Update:45 msgid "" "Optional. New incoming pre-checkout query. Contains full information " "about checkout" msgstr "" -#: of telebot.types.Update:41 +#: of telebot.types.Update:49 msgid "" "Optional. New poll state. Bots receive only updates about stopped polls " "and polls, which are sent by the bot" msgstr "" -#: of telebot.types.Update:45 +#: of telebot.types.Update:53 msgid "" "Optional. A user changed their answer in a non-anonymous poll. Bots " "receive new votes only in polls that were sent by the bot itself." msgstr "" -#: of telebot.types.Update:49 +#: of telebot.types.Update:57 msgid "" "Optional. The bot's chat member status was updated in a chat. For private" " chats, this update is received only when the bot is blocked or unblocked" " by the user." msgstr "" -#: of telebot.types.Update:53 +#: of telebot.types.Update:61 msgid "" "Optional. A chat member's status was updated in a chat. The bot must be " "an administrator in the chat and must explicitly specify “chat_member” in" " the list of allowed_updates to receive these updates." msgstr "" -#: of telebot.types.Update:57 +#: of telebot.types.Update:65 msgid "" "Optional. A request to join the chat has been sent. The bot must have the" " can_invite_users administrator right in the chat to receive these " "updates." msgstr "" -#: of telebot.types.Update:62 +#: of telebot.types.Update:69 +msgid "" +"Optional. A chat boost was added or changed. The bot must be an " +"administrator in the chat to receive these updates." +msgstr "" + +#: of telebot.types.Update:72 +msgid "" +"Optional. A chat boost was removed. The bot must be an administrator in " +"the chat to receive these updates." +msgstr "" + +#: of telebot.types.Update:76 msgid ":class:`telebot.types.Update`" msgstr "" @@ -5742,6 +6714,22 @@ msgstr "" msgid "return" msgstr "" +#: of telebot.types.UserChatBoosts:1 +msgid "This object represents a list of boosts added to a chat by a user." +msgstr "" + +#: of telebot.types.UserChatBoosts:3 +msgid "Telegram documentation: https://core.telegram.org/bots/api#userchatboosts" +msgstr "" + +#: of telebot.types.UserChatBoosts:5 +msgid "The list of boosts added to the chat by the user" +msgstr "" + +#: of telebot.types.UserChatBoosts:9 +msgid ":class:`UserChatBoosts`" +msgstr "" + #: of telebot.types.UserProfilePhotos:1 msgid "This object represent a user's profile pictures." msgstr "" @@ -5764,30 +6752,33 @@ msgstr "" msgid ":class:`telebot.types.UserProfilePhotos`" msgstr "" -#: of telebot.types.UserShared:1 +#: of telebot.types.UsersShared:1 msgid "" -"This object contains information about the user whose identifier was " -"shared with the bot using a `telebot.types.KeyboardButtonRequestUser` " -"button." +"This object contains information about the users whose identifiers were " +"shared with the bot using a KeyboardButtonRequestUsers button." msgstr "" -#: of telebot.types.UserShared:4 -msgid "Telegram documentation: https://core.telegram.org/bots/api#usershared" +#: of telebot.types.UsersShared:4 +msgid "Telegram documentation: https://core.telegram.org/bots/api#usersshared" msgstr "" -#: of telebot.types.UserShared:9 +#: of telebot.types.UsersShared:6 +msgid "Identifier of the request" +msgstr "" + +#: of telebot.types.UsersShared:9 msgid "" -"Identifier of the shared user. This number may have more than 32 " +"Identifiers of the shared users. These numbers may have more than 32 " "significant bits and some programming languages may have " -"difficulty/silent defects in interpreting it. But it has at most 52 " -"significant bits, so a 64-bit integer or double-precision float type are " -"safe for storing this identifier. The bot may not have access to the user" -" and could be unable to use this identifier, unless the user is already " -"known to the bot by some other means." +"difficulty/silent defects in interpreting them. But they have at most 52 " +"significant bits, so 64-bit integers or double-precision float types are " +"safe for storing these identifiers. The bot may not have access to the " +"users and could be unable to use these identifiers unless the users are " +"already known to the bot by some other means." msgstr "" -#: of telebot.types.UserShared:16 -msgid ":class:`telebot.types.UserShared`" +#: of telebot.types.UsersShared:18 +msgid ":class:`UsersShared`" msgstr "" #: of telebot.types.Venue:1 @@ -6065,20 +7056,34 @@ msgstr "" #: of telebot.types.WriteAccessAllowed:1 msgid "" -"This object represents a service message about a user allowed to post " -"messages in the chat. Currently holds no information." +"This object represents a service message about a user allowing a bot to " +"write messages after adding it to the attachment menu, launching a Web " +"App from a link, or accepting an explicit request from a Web App sent by " +"the method requestWriteAccess." msgstr "" -#: of telebot.types.WriteAccessAllowed:4 +#: of telebot.types.WriteAccessAllowed:5 msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#writeaccessallowed" msgstr "" -#: of telebot.types.WriteAccessAllowed:6 +#: of telebot.types.WriteAccessAllowed:7 +msgid "" +"Optional. True, if the access was granted after the user accepted an " +"explicit request from a Web App sent by the method requestWriteAccess" +msgstr "" + +#: of telebot.types.WriteAccessAllowed:11 msgid "Optional. Name of the Web App which was launched from a link" msgstr "" +#: of telebot.types.WriteAccessAllowed:14 +msgid "" +"Optional. True, if the access was granted when the bot was added to the " +"attachment or side menu" +msgstr "" + #~ msgid "Type of the result, must be animation" #~ msgstr "" @@ -6109,3 +7114,127 @@ msgstr "" #~ "can_send_media_messages" #~ msgstr "" +#~ msgid "" +#~ "Optional. Message with the callback " +#~ "button that originated the query. Note" +#~ " that message content and message " +#~ "date will not be available if the" +#~ " message is too old" +#~ msgstr "" + +#~ msgid "" +#~ "deprecated. True, if the user is " +#~ "allowed to send audios, documents, " +#~ "photos, videos, video notes and voice" +#~ " notes" +#~ msgstr "" + +#~ msgid "Optional. Disables link previews for links in the sent message" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. If specified, pressing the " +#~ "button will open a list of " +#~ "suitable users. Tapping on any user " +#~ "will send their identifier to the " +#~ "bot in a “user_shared” service message." +#~ " Available in private chats only." +#~ msgstr "" + +#~ msgid "" +#~ "Telegram documentation: " +#~ "https://core.telegram.org/bots/api#keyboardbuttonrequestuser" +#~ msgstr "" + +#~ msgid "" +#~ "Signed 32-bit identifier of the request," +#~ " which will be received back in " +#~ "the UserShared object. Must be unique" +#~ " within the message" +#~ msgstr "" + +#~ msgid ":class:`telebot.types.KeyboardButtonRequestUser`" +#~ msgstr "" + +#~ msgid "Optional. For forwarded messages, sender of the original message" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For messages forwarded from " +#~ "channels or from anonymous administrators, " +#~ "information about the original sender " +#~ "chat" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For messages forwarded from " +#~ "channels, identifier of the original " +#~ "message in the channel" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For forwarded messages that " +#~ "were originally sent in channels or " +#~ "by an anonymous chat administrator, " +#~ "signature of the message sender if " +#~ "present" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. Sender's name for messages " +#~ "forwarded from users who disallow adding" +#~ " a link to their account in " +#~ "forwarded messages" +#~ msgstr "" + +#~ msgid "" +#~ "Optional. For forwarded messages, date " +#~ "the original message was sent in " +#~ "Unix time" +#~ msgstr "" + +#~ msgid "The user, who changed the answer to the poll" +#~ msgstr "" + +#~ msgid "" +#~ "True, if the sticker set contains " +#~ "masks. Deprecated since Bot API 6.2, " +#~ "use sticker_type instead." +#~ msgstr "" + +#~ msgid "" +#~ "This object contains information about " +#~ "the user whose identifier was shared " +#~ "with the bot using a " +#~ "`telebot.types.KeyboardButtonRequestUser` button." +#~ msgstr "" + +#~ msgid "Telegram documentation: https://core.telegram.org/bots/api#usershared" +#~ msgstr "" + +#~ msgid "" +#~ "Identifier of the shared user. This " +#~ "number may have more than 32 " +#~ "significant bits and some programming " +#~ "languages may have difficulty/silent defects" +#~ " in interpreting it. But it has " +#~ "at most 52 significant bits, so a" +#~ " 64-bit integer or double-precision " +#~ "float type are safe for storing " +#~ "this identifier. The bot may not " +#~ "have access to the user and could" +#~ " be unable to use this identifier," +#~ " unless the user is already known " +#~ "to the bot by some other means." +#~ msgstr "" + +#~ msgid ":class:`telebot.types.UserShared`" +#~ msgstr "" + +#~ msgid "" +#~ "This object represents a service message" +#~ " about a user allowed to post " +#~ "messages in the chat. Currently holds" +#~ " no information." +#~ msgstr "" + From af95b5e2c1ad2d46d77bcdcddcd42a96e512a5cc Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Jan 2024 22:24:50 +0400 Subject: [PATCH 115/480] Update .readthedocs.yml --- .readthedocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index d157652e3..948e734bf 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -22,6 +22,5 @@ formats: all # Optionally set the version of Python and requirements required to build your docs python: - version: 3.11 install: - requirements: doc_req.txt From 1533e1a2e15739f7545aef7b14a2b5dfa4b61191 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Jan 2024 22:26:15 +0400 Subject: [PATCH 116/480] Delete .readthedocs.yaml --- .readthedocs.yaml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index ac48ea5a0..000000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# .readthedocs.yaml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -# Set the version of Python and other tools you might need -build: - os: ubuntu-22.04 - tools: - python: "3.9" - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/conf.py - -# We recommend specifying your dependencies to enable reproducible builds: -# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -python: - install: - - requirements: docs/requirements.txt From 83b744c86a4bb242029aece99e08cb979dde7b3d Mon Sep 17 00:00:00 2001 From: l27001 <65807480+l27001@users.noreply.github.com> Date: Sat, 6 Jan 2024 13:16:53 +0400 Subject: [PATCH 117/480] Translate get_user_chat_boosts in sync_version.po --- docs/source/locales/ru/LC_MESSAGES/sync_version.po | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/locales/ru/LC_MESSAGES/sync_version.po b/docs/source/locales/ru/LC_MESSAGES/sync_version.po index e304f04ad..b6e677773 100644 --- a/docs/source/locales/ru/LC_MESSAGES/sync_version.po +++ b/docs/source/locales/ru/LC_MESSAGES/sync_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-05 22:16+0400\n" +"POT-Creation-Date: 2024-01-06 13:16+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3149,16 +3149,16 @@ msgid "" "Requires administrator rights in the chat. Returns a UserChatBoosts " "object." msgstr "" -"Используйте этот метод, чтобы получить текущие права администратора для " -"бота по умолчанию. Возвращает объект ChatAdministratorRights в случае " -"успеха." +"Используйте этот метод, чтобы получить список бустов, полученных от " +"пользователя. Бот должен быть администратором чата. Возвращает объект " +"UserChatBoosts в случае успеха." #: of telebot.TeleBot.get_user_chat_boosts:3 #, fuzzy msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#getuserchatboosts" -msgstr "Документация Telegram: https://core.telegram.org/bots/api#getchat" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#getuserchatboosts" #: of telebot.TeleBot.get_user_chat_boosts:5 #: telebot.TeleBot.send_chat_action:10 telebot.TeleBot.send_contact:5 @@ -3170,12 +3170,12 @@ msgstr "Уникальный id чата или username канала" #: of telebot.TeleBot.get_user_chat_boosts:11 #, fuzzy msgid "On success, a UserChatBoosts object is returned." -msgstr "В случае успеха возвращается объект StickerSet." +msgstr "В случае успеха возвращается объект UserChatBoosts." #: of telebot.TeleBot.get_user_chat_boosts:12 #, fuzzy msgid ":class:`telebot.types.UserChatBoosts`" -msgstr "Экземпляр класса :class:`telebot.types.Message`" +msgstr "Экземпляр класса :class:`telebot.types.UserChatBoosts`" #: of telebot.TeleBot.get_user_profile_photos:1 msgid "" From aa6695e3c0baa09b276077c60e9d9d4b265ffe2c Mon Sep 17 00:00:00 2001 From: l27001 <65807480+l27001@users.noreply.github.com> Date: Sat, 6 Jan 2024 13:19:05 +0400 Subject: [PATCH 118/480] Translate get_user_chat_boosts in async_version.po --- .../source/locales/ru/LC_MESSAGES/async_version.po | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/locales/ru/LC_MESSAGES/async_version.po b/docs/source/locales/ru/LC_MESSAGES/async_version.po index 570c22026..e4547a9be 100644 --- a/docs/source/locales/ru/LC_MESSAGES/async_version.po +++ b/docs/source/locales/ru/LC_MESSAGES/async_version.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: pyTelegramBotAPI Documentation \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-01-05 22:16+0400\n" +"POT-Creation-Date: 2024-01-06 13:19+0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3328,16 +3328,16 @@ msgid "" "Requires administrator rights in the chat. Returns a UserChatBoosts " "object." msgstr "" -"Используйте этот метод, чтобы получить текущие права администратора для " -"бота по умолчанию. Возвращает объект ChatAdministratorRights в случае " -"успеха." +"Используйте этот метод, чтобы получить список бустов, полученных от " +"пользователя. Бот должен быть администратором чата. Возвращает объект " +"UserChatBoosts в случае успеха." #: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:3 #, fuzzy msgid "" "Telegram documentation: " "https://core.telegram.org/bots/api#getuserchatboosts" -msgstr "Документация Telegram: https://core.telegram.org/bots/api#getchat" +msgstr "Документация Telegram: https://core.telegram.org/bots/api#getuserchatboosts" #: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:5 #: telebot.async_telebot.AsyncTeleBot.send_chat_action:10 @@ -3351,12 +3351,12 @@ msgstr "Уникальный id чата или username канала" #: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:11 #, fuzzy msgid "On success, a UserChatBoosts object is returned." -msgstr "В случае успеха, возвращается объект StickerSet." +msgstr "В случае успеха, возвращается объект UserChatBoosts." #: of telebot.async_telebot.AsyncTeleBot.get_user_chat_boosts:12 #, fuzzy msgid ":class:`telebot.types.UserChatBoosts`" -msgstr "Экземпляр класса :class:`telebot.types.Message`" +msgstr "Экземпляр класса :class:`telebot.types.UserChatBoosts`" #: of telebot.async_telebot.AsyncTeleBot.get_user_profile_photos:1 msgid "" From 3b17169579e57f204e3636158c1575ffd4158f58 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 8 Jan 2024 18:56:23 +0300 Subject: [PATCH 119/480] Bump version to 4.15.0 --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 321ff4966..c36bb58d7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.14.1' +release = '4.15.0' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index d06b2f7a7..cd7b2ebfa 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.14.1' +__version__ = '4.15.0' From 956c2697a201e0ef03b16bc064a2367b73b2785f Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 10 Jan 2024 17:59:06 +0400 Subject: [PATCH 120/480] Update types.py --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index c98af1fad..f3737d381 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3814,7 +3814,7 @@ def __init__( self.message_text: str = message_text self.parse_mode: str = parse_mode self.entities: List[MessageEntity] = entities - link_preview_options: LinkPreviewOptions = link_preview_options + self.link_preview_options: LinkPreviewOptions = link_preview_options if disable_web_page_preview is not None: logger.warning('The parameter "disable_web_page_preview" is deprecated. Use "link_preview_options" instead.') From e5f5bb3b2acca4e8e7e657d9a31ac6465c9d0485 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 11 Jan 2024 00:33:37 +0300 Subject: [PATCH 121/480] Fix disable_web_page_preview in LinkPreviewOptions --- telebot/__init__.py | 16 ++++++---------- telebot/async_telebot.py | 4 ++-- telebot/types.py | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index fb49abdc0..405c718b4 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1657,12 +1657,10 @@ def send_message( logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") else: # create a LinkPreviewOptions object - link_preview_options = types.LinkPreviewOptions( - disable_web_page_preview=disable_web_page_preview - ) + link_preview_options = types.LinkPreviewOptions(is_disabled=disable_web_page_preview) - if link_preview_options and (link_preview_options.disable_web_page_preview is None): - link_preview_options.disable_web_page_preview = self.disable_web_page_preview + if link_preview_options and (link_preview_options.is_disabled is None): + link_preview_options.is_disabled = self.disable_web_page_preview return types.Message.de_json( apihelper.send_message( @@ -4433,12 +4431,10 @@ def edit_message_text( logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") else: # create a LinkPreviewOptions object - link_preview_options = types.LinkPreviewOptions( - disable_web_page_preview=disable_web_page_preview - ) + link_preview_options = types.LinkPreviewOptions(is_disabled=disable_web_page_preview) - if link_preview_options and (link_preview_options.disable_web_page_preview is None): - link_preview_options.disable_web_page_preview = self.disable_web_page_preview + if link_preview_options and (link_preview_options.is_disabled is None): + link_preview_options.is_disabled = self.disable_web_page_preview result = apihelper.edit_message_text( self.token, text, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 3e8b305a3..efdcd0cae 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2716,7 +2716,7 @@ async def send_message( # create a LinkPreviewOptions object link_preview_options = types.LinkPreviewOptions( - disable_web_page_preview=disable_web_page_preview + is_disabled=disable_web_page_preview ) return types.Message.de_json( @@ -5294,7 +5294,7 @@ async def edit_message_text( # create a LinkPreviewOptions object link_preview_options = types.LinkPreviewOptions( - disable_web_page_preview=disable_web_page_preview + is_disabled=disable_web_page_preview ) result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, diff --git a/telebot/types.py b/telebot/types.py index f3737d381..5584d13f5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3821,7 +3821,7 @@ def __init__( if link_preview_options: logger.warning('Both "link_preview_options" and "disable_web_page_preview" parameters are set: conflicting, "disable_web_page_preview" is deprecated') else: - self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(disable_web_page_preview) + self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(is_disabled=disable_web_page_preview) def to_dict(self): json_dict = {'message_text': self.message_text} From be2c1e498721420f1b7d20f69b73d517d89d6934 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 12 Jan 2024 20:51:23 +0400 Subject: [PATCH 122/480] Changes in deprecated parameters for async --- telebot/async_telebot.py | 581 ++++++++++++++++++++++++++------------- 1 file changed, 386 insertions(+), 195 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index efdcd0cae..38f1ef1c8 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -111,7 +111,7 @@ class AsyncTeleBot: :param protect_content: Default value for protect_content, defaults to None :type protect_content: :obj:`bool`, optional - :param allow_sending_without_reply: Default value for allow_sending_without_reply, defaults to None + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Default value for allow_sending_without_reply, defaults to None :type allow_sending_without_reply: :obj:`bool`, optional :param colorful_logs: Outputs colorful logs @@ -2661,7 +2661,7 @@ async def send_message( :param entities: List of special entities that appear in message text, which can be specified instead of parse_mode :type entities: Array of :class:`telebot.types.MessageEntity` - :param disable_web_page_preview: Disables link previews for links in this message + :param disable_web_page_preview: Deprecated - Use link_preview_options instead. :type disable_web_page_preview: :obj:`bool` :param disable_notification: Sends the message silently. Users will receive a notification with no sound. @@ -2670,10 +2670,10 @@ async def send_message( :param protect_content: If True, the message content will be hidden for all users except for the target user :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -2699,25 +2699,43 @@ async def send_message( disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) - if disable_web_page_preview: + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + + if disable_web_page_preview is not None: # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + + if link_preview_options: + # show a conflict warning + logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") + else: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + is_disabled=disable_web_page_preview + ) - # create a LinkPreviewOptions object - link_preview_options = types.LinkPreviewOptions( - is_disabled=disable_web_page_preview - ) + if link_preview_options and (link_preview_options.is_disabled is None): + link_preview_options.is_disabled = self.disable_web_page_preview return types.Message.de_json( await asyncio_helper.send_message( @@ -2810,10 +2828,10 @@ async def copy_message( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -2836,17 +2854,26 @@ async def copy_message( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.MessageID.de_json( await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, @@ -2995,7 +3022,7 @@ async def send_dice( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions @@ -3006,7 +3033,7 @@ async def send_dice( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param protect_content: Protects the contents of the sent message from forwarding @@ -3023,17 +3050,27 @@ async def send_dice( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_dice( @@ -3082,10 +3119,10 @@ async def send_photo( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions @@ -3111,17 +3148,27 @@ async def send_photo( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_photo( @@ -3174,7 +3221,7 @@ async def send_audio( :param title: Track name :type title: :obj:`str` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: @@ -3199,7 +3246,7 @@ async def send_audio( :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -3220,21 +3267,31 @@ async def send_audio( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if thumb is not None and thumbnail is None: thumbnail = thumb logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_audio( @@ -3275,7 +3332,7 @@ async def send_voice( :param duration: Duration of the voice message in seconds :type duration: :obj:`int` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions @@ -3295,7 +3352,7 @@ async def send_voice( :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -3312,17 +3369,27 @@ async def send_voice( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_voice( @@ -3360,7 +3427,7 @@ async def send_document( String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data :type document: :obj:`str` or :class:`telebot.types.InputFile` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param caption: Document caption (may also be used when resending documents by file_id), 0-1024 characters after entities parsing @@ -3386,7 +3453,7 @@ async def send_document( :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param visible_file_name: allows to define file name that will be visible in the Telegram instead of original file name @@ -3416,7 +3483,7 @@ async def send_document( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if data and not(document): # function typo miss compatibility @@ -3427,15 +3494,25 @@ async def send_document( thumbnail = thumb logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_data( @@ -3471,7 +3548,7 @@ async def send_sticker( as a String for Telegram to get a .webp file from the Internet, or upload a new one using multipart/form-data. :type sticker: :obj:`str` or :class:`telebot.types.InputFile` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -3485,7 +3562,7 @@ async def send_sticker( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -3508,22 +3585,32 @@ async def send_sticker( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + if data and not(sticker): # function typo miss compatibility logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_data( @@ -3595,10 +3682,10 @@ async def send_video( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -3630,17 +3717,27 @@ async def send_video( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if data and not(video): # function typo miss compatibility @@ -3713,7 +3810,7 @@ async def send_animation( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -3730,7 +3827,7 @@ async def send_animation( :param caption_entities: List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param message_thread_id: Identifier of a message thread, in which the video will be sent @@ -3751,17 +3848,27 @@ async def send_animation( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumb is not None and thumbnail is None: thumbnail = thumb @@ -3806,7 +3913,7 @@ async def send_video_note( :param length: Video width and height, i.e. diameter of the video message :type length: :obj:`int` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -3826,7 +3933,7 @@ async def send_video_note( so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -3846,17 +3953,27 @@ async def send_video_note( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if thumb is not None and thumbnail is None: thumbnail = thumb @@ -3897,13 +4014,13 @@ async def send_media_group( :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param message_thread_id: Identifier of a message thread, in which the messages will be sent @@ -3917,17 +4034,27 @@ async def send_media_group( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = await asyncio_helper.send_media_group( self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters) @@ -3965,7 +4092,7 @@ async def send_location( :param live_period: Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400. :type live_period: :obj:`int` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard @@ -3988,7 +4115,7 @@ async def send_location( :param proximity_alert_radius: For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -4005,17 +4132,27 @@ async def send_location( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_location( @@ -4162,7 +4299,7 @@ async def send_venue( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, @@ -4173,7 +4310,7 @@ async def send_venue( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if one of the specified replied-to messages is not found. :type allow_sending_without_reply: :obj:`bool` @@ -4197,17 +4334,27 @@ async def send_venue( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_venue( @@ -4251,7 +4398,7 @@ async def send_contact( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, @@ -4262,7 +4409,7 @@ async def send_contact( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if one of the specified replied-to messages is not found. :type allow_sending_without_reply: :obj:`bool` @@ -4280,17 +4427,27 @@ async def send_contact( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.Message.de_json( await asyncio_helper.send_contact( @@ -5273,7 +5430,7 @@ async def edit_message_text( :param entities: List of special entities that appear in the message text, which can be specified instead of parse_mode :type entities: List of :obj:`telebot.types.MessageEntity` - :param disable_web_page_preview: Disables link previews for links in this message + :param disable_web_page_preview: Deprecated - Use link_preview_options instead. :type disable_web_page_preview: :obj:`bool` :param reply_markup: A JSON-serialized object for an inline keyboard. @@ -5288,14 +5445,18 @@ async def edit_message_text( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview - if disable_web_page_preview: - # show a deprecation warning - logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") + if disable_web_page_preview is not None: + if link_preview_options: + # show a conflict warning + logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") + else: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions( + is_disabled=disable_web_page_preview + ) - # create a LinkPreviewOptions object - link_preview_options = types.LinkPreviewOptions( - is_disabled=disable_web_page_preview - ) + if link_preview_options and (link_preview_options.is_disabled is None): + link_preview_options.is_disabled = self.disable_web_page_preview result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, entities, reply_markup, link_preview_options) @@ -5392,7 +5553,7 @@ async def send_game( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -5401,7 +5562,7 @@ async def send_game( :param timeout: Timeout in seconds for waiting for a response from the bot. :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if one of the specified replied-to messages is not found. + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if one of the specified replied-to messages is not found. :type allow_sending_without_reply: :obj:`bool` :param protect_content: Pass True, if content of the message needs to be protected from being viewed by the bot. @@ -5418,17 +5579,27 @@ async def send_game( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = await asyncio_helper.send_game( self.token, chat_id, game_short_name, disable_notification, @@ -5602,7 +5773,7 @@ async def send_invoice( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, @@ -5616,7 +5787,7 @@ async def send_invoice( :param timeout: Timeout of a request, defaults to None :type timeout: :obj:`int` - :param allow_sending_without_reply: Pass True, if the message should be sent even if the specified replied-to message is not found + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency @@ -5641,17 +5812,27 @@ async def send_invoice( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = await asyncio_helper.send_invoice( self.token, chat_id, title, description, invoice_payload, provider_token, @@ -5833,10 +6014,10 @@ async def send_poll( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` - :param allow_sending_without_reply: Pass True, if the poll allows multiple options to be voted simultaneously. + :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the poll allows multiple options to be voted simultaneously. :type allow_sending_without_reply: :obj:`bool` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, @@ -5864,18 +6045,28 @@ async def send_poll( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - allow_sending_without_reply = self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode - if allow_sending_without_reply or reply_to_message_id: + if allow_sending_without_reply is not None: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + + if reply_to_message_id: # show a deprecation warning - logger.warning("The parameters 'allow_sending_without_reply' and 'reply_to_message_id' are deprecated. Use 'reply_parameters' instead.") + logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") + + if reply_parameters: + # show a conflict warning + logger.warning("Both 'reply_parameters' and 'reply_to_message_id' parameters are set: conflicting, 'reply_to_message_id' is deprecated") + else: + # create a ReplyParameters object + reply_parameters = types.ReplyParameters( + reply_to_message_id, + allow_sending_without_reply=self.allow_sending_without_reply if (allow_sending_without_reply is None) else allow_sending_without_reply + ) - # create a ReplyParameters object - reply_parameters = types.ReplyParameters( - allow_sending_without_reply=allow_sending_without_reply, - message_id=reply_to_message_id - ) + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply if isinstance(question, types.Poll): raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") From a8252d7d9d9fda39cfda55d3a3140534f22ab81a Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 12 Jan 2024 21:12:54 +0400 Subject: [PATCH 123/480] Added mcite and hcite support to formatting --- telebot/formatting.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/telebot/formatting.py b/telebot/formatting.py index 32a09fe2d..c0f442013 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -324,3 +324,37 @@ def hide_link(url: str) -> str: :rtype: :obj:`str` """ return f'' + + +def mcite(content: str, escape: Optional[bool]=True) -> str: + """ + Returns a Markdown-formatted block-quotation string. + + :param content: The string to bold. + :type content: :obj:`str` + + :param escape: True if you need to escape special characters. Defaults to True. + :type escape: :obj:`bool` + + :return: The formatted string. + :rtype: :obj:`str` + """ + content = escape_markdown(content) if escape else content + content = '\n'.join(['>' + line for line in content.split('\n')]) + return content + + +def hcite(content: str, escape: Optional[bool]=True) -> str: + """ + Returns a html-formatted block-quotation string. + + :param content: The string to bold. + :type content: :obj:`str` + + :param escape: True if you need to escape special characters. Defaults to True. + :type escape: :obj:`bool` + + :return: The formatted string. + :rtype: :obj:`str` + """ + return '
{}
'.format(escape_html(content) if escape else content) From eb48a5a153a7262840d1b24f35ef8da7e6464023 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 12 Jan 2024 21:23:35 +0400 Subject: [PATCH 124/480] Add support for blockquote parsing for html_text for messages --- telebot/types.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 5584d13f5..91f48f0ea 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1416,7 +1416,8 @@ def __html_text(self, text, entities): "strikethrough": "{text}", "underline": "{text}", "spoiler": "{text}", - "custom_emoji": "{text}" + "custom_emoji": "{text}", + "blockquote": "
{text}
", } if hasattr(self, "custom_subs"): From 36cfe9060af8aaebbfeb26e630fa72551efab147 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 12 Jan 2024 21:40:41 +0400 Subject: [PATCH 125/480] Revert parameter sequences for sync --- telebot/__init__.py | 46 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 405c718b4..466f939ce 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1939,10 +1939,10 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], def send_dice( self, chat_id: Union[int, str], emoji: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -2118,14 +2118,14 @@ def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], caption: Optional[str]=None, duration: Optional[int]=None, performer: Optional[str]=None, title: Optional[str]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, @@ -2240,13 +2240,13 @@ def send_audio( def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], caption: Optional[str]=None, duration: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, caption_entities: Optional[List[types.MessageEntity]]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -2337,15 +2337,15 @@ def send_voice( def send_document( self, chat_id: Union[int, str], document: Union[Any, str], + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility caption: Optional[str]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility visible_file_name: Optional[str]=None, disable_content_type_detection: Optional[bool]=None, data: Optional[Union[Any, str]]=None, @@ -2460,11 +2460,11 @@ def send_document( def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content:Optional[bool]=None, data: Union[Any, str]=None, message_thread_id: Optional[int]=None, @@ -2818,12 +2818,12 @@ def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], duration: Optional[int]=None, length: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, @@ -2926,8 +2926,8 @@ def send_media_group( disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]: """ @@ -2996,15 +2996,15 @@ def send_media_group( def send_location( self, chat_id: Union[int, str], latitude: float, longitude: float, - live_period: Optional[int]=None, + live_period: Optional[int]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, horizontal_accuracy: Optional[float]=None, heading: Optional[int]=None, - proximity_alert_radius: Optional[int]=None, + proximity_alert_radius: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -3198,9 +3198,9 @@ def send_venue( foursquare_type: Optional[str]=None, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility google_place_id: Optional[str]=None, google_place_type: Optional[str]=None, protect_content: Optional[bool]=None, @@ -3304,9 +3304,9 @@ def send_contact( vcard: Optional[str]=None, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: """ @@ -4522,9 +4522,9 @@ def send_game( self, chat_id: Union[int, str], game_short_name: str, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: @@ -4690,10 +4690,10 @@ def send_invoice( is_flexible: Optional[bool]=None, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, provider_data: Optional[str]=None, timeout: Optional[int]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, protect_content: Optional[bool]=None, @@ -4962,8 +4962,8 @@ def send_poll( is_closed: Optional[bool]=None, disable_notification: Optional[bool]=False, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, From ed66dba4d54140a5e7f8d3c01152afd69d69fb71 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 14 Jan 2024 13:17:19 +0400 Subject: [PATCH 126/480] Fixing docstrings (#2126) --- telebot/__init__.py | 23 +++++++++++++++++------ telebot/async_telebot.py | 24 +++++++++++++++++------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 466f939ce..b7df22505 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1368,7 +1368,9 @@ def close(self) -> bool: def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: """ - Use this method to set a reaction to a message in a chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + 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. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmessagereaction @@ -1841,9 +1843,7 @@ def delete_message(self, chat_id: Union[int, str], message_id: int, def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ - Use this method to delete multiple messages in a chat. - The number of messages to be deleted must not exceed 100. - If the chat is a private chat, the user must be an administrator of the chat for this to work and must have the appropriate admin rights. + Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they are skipped. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#deletemessages @@ -1863,7 +1863,11 @@ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: """ - Use this method to forward messages of any kind. + Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, they are skipped. + Service messages and messages with protected content can't be forwarded. Album grouping is kept for forwarded messages. + On success, an array of MessageId of the sent messages is returned. + + Telegram documentation: https://core.telegram.org/bots/api#forwardmessages :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -1901,7 +1905,14 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: """ - Use this method to copy messages of any kind. + Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. + Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. + A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. + The method is analogous to the method forwardMessages, but the copied messages don't have a link to the original message. + Album grouping is kept for copied messages. On success, an array of MessageId of the sent messages is returned. + + Telegram documentation: https://core.telegram.org/bots/api#copymessages + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 38f1ef1c8..dd61a9ad6 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2422,7 +2422,9 @@ async def get_webhook_info(self, timeout: Optional[int]=None) -> types.WebhookIn async def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: """ - Use this method to set a reaction to a message in a chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. + 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. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmessagereaction @@ -2911,10 +2913,8 @@ async def delete_message(self, chat_id: Union[int, str], message_id: int, async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ - Use this method to delete multiple messages in a chat. - The number of messages to be deleted must not exceed 100. - If the chat is a private chat, the user must be an administrator of the chat for this to work and must have the appropriate admin rights. - Returns True on success. + Use this method to delete multiple messages simultaneously. + If some of the specified messages can't be found, they are skipped. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#deletemessages @@ -2932,7 +2932,11 @@ async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int] async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: """ - Use this method to forward messages of any kind. + Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, + they are skipped. Service messages and messages with protected content can't be forwarded. + Album grouping is kept for forwarded messages. On success, an array of MessageId of the sent messages is returned. + + Telegram documentation: https://core.telegram.org/bots/api#forwardmessages :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2965,7 +2969,13 @@ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: """ - Use this method to copy messages of any kind. + Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. + Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can be copied + only if the value of the field correct_option_id is known to the bot. The method is analogous to the method forwardMessages, but + the copied messages don't have a link to the original message. Album grouping is kept for copied messages. + On success, an array of MessageId of the sent messages is returned. + + Telegram documentation: https://core.telegram.org/bots/api#copymessages :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` From f7403f3672144714fdb9cdc49ef1f7d99d55fbfe Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 14 Jan 2024 17:43:28 +0400 Subject: [PATCH 127/480] Update apihelper.py --- telebot/apihelper.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d307e9bae..b8f4e7855 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1897,7 +1897,7 @@ def delete_messages(token, chat_id, message_ids): method_url = 'deleteMessages' payload = { 'chat_id': chat_id, - 'message_ids': message_ids + 'message_ids': json.dumps(message_ids) } return _make_request(token, method_url, params=payload) @@ -1907,7 +1907,7 @@ def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notifica payload = { 'chat_id': chat_id, 'from_chat_id': from_chat_id, - 'message_ids': message_ids, + 'message_ids': json.dumps(message_ids), } if disable_notification is not None: payload['disable_notification'] = disable_notification @@ -1923,7 +1923,7 @@ def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notificatio payload = { 'chat_id': chat_id, 'from_chat_id': from_chat_id, - 'message_ids': message_ids, + 'message_ids': json.dumps(message_ids), } if disable_notification is not None: payload['disable_notification'] = disable_notification From 4eecc5ea2f1c76213721199d39677043e10f942f Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 14 Jan 2024 17:45:11 +0400 Subject: [PATCH 128/480] Update asyncio_helper.py --- telebot/asyncio_helper.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 872fb591d..c7d4df835 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1879,7 +1879,7 @@ async def delete_messages(token, chat_id, message_ids): method_url = 'deleteMessages' payload = { 'chat_id': chat_id, - 'message_ids': message_ids + 'message_ids': json.dumps(message_ids) } return await _process_request(token, method_url, params=payload) @@ -1889,7 +1889,7 @@ async def forward_messages(token, chat_id, from_chat_id, message_ids, disable_no payload = { 'chat_id': chat_id, 'from_chat_id': from_chat_id, - 'message_ids': message_ids, + 'message_ids': json.dumps(message_ids), } if disable_notification is not None: payload['disable_notification'] = disable_notification @@ -1907,7 +1907,7 @@ async def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notif payload = { 'chat_id': chat_id, 'from_chat_id': from_chat_id, - 'message_ids': message_ids, + 'message_ids': json.dumps(message_ids), } if disable_notification is not None: payload['disable_notification'] = disable_notification From eaa64bb6c09bd084fb5b5ba9eadc652017f531cc Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 14 Jan 2024 16:51:01 +0300 Subject: [PATCH 129/480] Bugfix: fix link_preview_options passing for Telebot --- telebot/apihelper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d307e9bae..7c22f4742 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -244,7 +244,7 @@ def send_message( method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: - payload['link_preview'] = link_preview_options.to_json() + payload['link_preview_options'] = link_preview_options.to_json() if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if parse_mode: @@ -1304,7 +1304,7 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if link_preview_options is not None: - payload['link_preview'] = link_preview_options.to_json() + payload['link_preview_options'] = link_preview_options.to_json() return _make_request(token, method_url, params=payload, method='post') From 38568bde31af5fb203f7ed9c525449d1c7b67a48 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 14 Jan 2024 18:18:29 +0300 Subject: [PATCH 130/480] Bump version to 4.15.1 (bugfix) --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index c36bb58d7..663b23c53 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.15.0' +release = '4.15.1' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index cd7b2ebfa..0282ef2a7 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.15.0' +__version__ = '4.15.1' From 34cf5494232533f8b1f816fcbbfe782b6205da29 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 14 Jan 2024 20:41:07 +0300 Subject: [PATCH 131/480] Deprecation: stubs for Message fields in InaccessibleMessage --- telebot/types.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 91f48f0ea..ca4c3c028 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1451,13 +1451,13 @@ def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): html_text += func(utf16_text[offset * 2 : entity.offset * 2]) offset = entity.offset - new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user, entity.custom_emoji_id) + new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], subst_type=entity.type, url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) start_index = len(html_text) html_text += new_string offset += entity.length end_index = len(html_text) elif entity.offset == offset: - new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], entity.type, entity.url, entity.user, entity.custom_emoji_id) + new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], subst_type=entity.type, url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) start_index = len(html_text) html_text += new_string end_index = len(html_text) @@ -1468,7 +1468,8 @@ def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, # And we don't change it). entity_string = html_text[start_index : end_index].encode("utf-16-le") - formatted_string = func(entity_string, entity.type, entity.url, entity.user, entity.custom_emoji_id).replace("&", "&").replace("<", "<").replace(">",">") + formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id).\ + replace("&", "&").replace("<", "<").replace(">",">") html_text = html_text[:start_index] + formatted_string + html_text[end_index:] end_index = len(html_text) @@ -9214,3 +9215,28 @@ def __init__(self, chat, message_id, date, **kwargs): self.chat = chat self.message_id = message_id self.date = date + + @staticmethod + def __universal_deprecation(property_name): + logger.warning(f'Deprecation warning: the filed "{property_name}" is not accessible for InaccessibleMessage. You should check if your object is Message instance before access.') + return None + + def __getattr__(self, item): + if item in [ + 'message_thread_id', 'from_user', 'sender_chat', 'forward_origin', 'is_topic_message', + 'is_automatic_forward', 'reply_to_message', 'external_reply', 'qoute', 'via_bot', 'edit_date', + 'has_protected_content', 'media_group_id', 'author_signature', 'text', 'entities', 'link_preview_options', + 'animation', 'audio', 'document', 'photo', 'sticker', 'story', 'video', 'video_note', 'voice', 'caption', + 'caption_entities', 'has_media_spoiler', 'contact', 'dice', 'game', 'poll', 'venue', 'location', + 'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', + 'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'message_auto_delete_timer_changed', + 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message', 'invoice', 'successful_payment', + 'users_shared', 'chat_shared', 'connected_website', 'write_access_allowed', 'passport_data', + 'proximity_alert_triggered', 'forum_topic_created', 'forum_topic_edited', 'forum_topic_closed', + 'forum_topic_reopened', 'general_forum_topic_hidden', 'general_forum_topic_unhidden', 'giveaway_created', + 'giveaway', 'giveaway_winners', 'giveaway_completed', 'video_chat_scheduled', 'video_chat_started', + 'video_chat_ended', 'video_chat_participants_invited', 'web_app_data', 'reply_markup' + ]: + return self.__universal_deprecation(item) + else: + raise AttributeError(f'"{self.__class__.__name__}" object has no attribute "{item}"') From a28f9503cf2707f7a03800e932212ac2b6357bed Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 15 Jan 2024 09:34:17 +0300 Subject: [PATCH 132/480] Bump version to 4.15.2 --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 663b23c53..18ad5d829 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.15.1' +release = '4.15.2' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index 0282ef2a7..4757b8468 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.15.1' +__version__ = '4.15.2' From e8b2118bc1944c88bf16065e9a0b599842a2ce55 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 21 Jan 2024 12:06:20 +0300 Subject: [PATCH 133/480] Fix ChatBoostSource issues 1. "source" is temporary made optional 2. source types are parsed correctly --- telebot/types.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index ca4c3c028..a34fb855f 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9000,9 +9000,12 @@ def __init__(self, chat, boost_id, remove_date, source, **kwargs): self.source = source -class ChatBoostSource(JsonDeserializable): +class ChatBoostSource(ABC, JsonDeserializable): """ - This object describes the source of a chat boost. + This object describes the source of a chat boost. It can be one of + ChatBoostSourcePremium + ChatBoostSourceGiftCode + ChatBoostSourceGiveaway Telegram documentation: https://core.telegram.org/bots/api#chatboostsource @@ -9010,7 +9013,7 @@ class ChatBoostSource(JsonDeserializable): :type source: :obj:`str` :return: Instance of the class - :rtype: :class:`ChatBoostSource` + :rtype: :class:`ChatBoostSourcePremium` or :class:`ChatBoostSourceGiftCode` or :class:`ChatBoostSourceGiveaway` """ @classmethod @@ -9018,10 +9021,13 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - return cls(**obj) - - def __init__(self, source, **kwargs): - self.source = source + if obj["type"] == "premium": + return ChatBoostSourcePremium.de_json(obj) + elif obj["type"] == "gift_code": + return ChatBoostSourceGiftCode.de_json(obj) + elif obj["type"] == "giveaway": + return ChatBoostSourceGiveaway.de_json(obj) + return None # noinspection PyUnresolvedReferences @@ -9137,10 +9143,10 @@ class ChatBoost(JsonDeserializable): :param expiration_date: Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium subscription is prolonged :type expiration_date: :obj:`int` - :param source: Source of the added boost + :param source: Optional. Source of the added boost (made Optional for now due to API error) :type source: :class:`ChatBoostSource` - :return: Instance of the class + :return: Instance of the class (made Optional for now due to API error) :rtype: :class:`ChatBoost` """ @@ -9149,7 +9155,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['source'] = ChatBoostSource.de_json(obj['source']) + source = obj.get('source', None) + obj['source'] = ChatBoostSource.de_json(source) if source else None return cls(**obj) def __init__(self, boost_id, add_date, expiration_date, source, **kwargs): From 5844b2eff35908e3dbeaec1f1fd10094030a1d97 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 21 Jan 2024 12:08:19 +0300 Subject: [PATCH 134/480] Description fix --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index a34fb855f..d35676893 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9146,7 +9146,7 @@ class ChatBoost(JsonDeserializable): :param source: Optional. Source of the added boost (made Optional for now due to API error) :type source: :class:`ChatBoostSource` - :return: Instance of the class (made Optional for now due to API error) + :return: Instance of the class :rtype: :class:`ChatBoost` """ From 9d37128bcd0f5d8bbd2288db28b5f8b3a212eb02 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 26 Jan 2024 13:10:28 +0300 Subject: [PATCH 135/480] Bump version to 4.15.3 --- docs/source/conf.py | 2 +- telebot/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 18ad5d829..ee8ed1f30 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.15.2' +release = '4.15.3' # -- General configuration --------------------------------------------------- diff --git a/telebot/version.py b/telebot/version.py index 4757b8468..89fb4bff9 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.15.2' +__version__ = '4.15.3' From 6f43238be65a89d21a99ff457229d9048c5bc253 Mon Sep 17 00:00:00 2001 From: Evgeniy Khlusov Date: Tue, 30 Jan 2024 15:30:00 +0300 Subject: [PATCH 136/480] Fix preview link options if link_preview_options not provided. Get param from class --- telebot/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index b7df22505..6e1e5040a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1664,6 +1664,11 @@ def send_message( if link_preview_options and (link_preview_options.is_disabled is None): link_preview_options.is_disabled = self.disable_web_page_preview + # Fix preview link options if link_preview_options not provided. Get param from class + if not link_preview_options and self.disable_web_page_preview: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions(is_disabled=self.disable_web_page_preview) + return types.Message.de_json( apihelper.send_message( self.token, chat_id, text, From 9014839bcb62f767e915f2ee27acaaeea3e29d48 Mon Sep 17 00:00:00 2001 From: ekhlusov Date: Tue, 30 Jan 2024 18:20:51 +0300 Subject: [PATCH 137/480] Fix preview link options if link_preview_options not provided in async telebot --- telebot/__init__.py | 5 +++++ telebot/async_telebot.py | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 6e1e5040a..f977139cc 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4452,6 +4452,11 @@ def edit_message_text( if link_preview_options and (link_preview_options.is_disabled is None): link_preview_options.is_disabled = self.disable_web_page_preview + # Fix preview link options if link_preview_options not provided. Get param from class + if not link_preview_options and self.disable_web_page_preview: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions(is_disabled=self.disable_web_page_preview) + result = apihelper.edit_message_text( self.token, text, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, parse_mode=parse_mode, entities=entities, reply_markup=reply_markup, link_preview_options=link_preview_options) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index dd61a9ad6..2adf4275c 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2739,6 +2739,11 @@ async def send_message( if link_preview_options and (link_preview_options.is_disabled is None): link_preview_options.is_disabled = self.disable_web_page_preview + # Fix preview link options if link_preview_options not provided. Get param from class + if not link_preview_options and self.disable_web_page_preview: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions(is_disabled=self.disable_web_page_preview) + return types.Message.de_json( await asyncio_helper.send_message( self.token, chat_id, text, @@ -5468,6 +5473,11 @@ async def edit_message_text( if link_preview_options and (link_preview_options.is_disabled is None): link_preview_options.is_disabled = self.disable_web_page_preview + # Fix preview link options if link_preview_options not provided. Get param from class + if not link_preview_options and self.disable_web_page_preview: + # create a LinkPreviewOptions object + link_preview_options = types.LinkPreviewOptions(is_disabled=self.disable_web_page_preview) + result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, entities, reply_markup, link_preview_options) if type(result) == bool: # if edit inline message return is bool not Message. From 4b1422f79c39e7284e38bec8367679e13823047b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Tue, 30 Jan 2024 19:50:19 +0300 Subject: [PATCH 138/480] Bug in ChatBoostSource parse --- docs/source/conf.py | 2 +- telebot/types.py | 6 +++--- telebot/version.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index ee8ed1f30..b4369c1c2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.15.3' +release = '4.15.4' # -- General configuration --------------------------------------------------- diff --git a/telebot/types.py b/telebot/types.py index d35676893..dce297af7 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9021,11 +9021,11 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - if obj["type"] == "premium": + if obj["source"] == "premium": return ChatBoostSourcePremium.de_json(obj) - elif obj["type"] == "gift_code": + elif obj["source"] == "gift_code": return ChatBoostSourceGiftCode.de_json(obj) - elif obj["type"] == "giveaway": + elif obj["source"] == "giveaway": return ChatBoostSourceGiveaway.de_json(obj) return None diff --git a/telebot/version.py b/telebot/version.py index 89fb4bff9..1e29eda03 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.15.3' +__version__ = '4.15.4' From 64e503c4e705fc2246389e1486d00f8c808ccf71 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 3 Feb 2024 20:30:34 +0300 Subject: [PATCH 139/480] Fix deprecated parameters 1. Fix descriptions 2. Fix bot.reply_to function 3. Fix ChatPermissions.de_json --- telebot/__init__.py | 51 +++++++++++++++++++++------------------ telebot/apihelper.py | 2 -- telebot/async_telebot.py | 44 ++++++++++++++++++--------------- telebot/asyncio_helper.py | 2 -- telebot/types.py | 21 +++++++++------- 5 files changed, 65 insertions(+), 55 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index f977139cc..0c7ef6e22 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3547,48 +3547,43 @@ def restrict_chat_member( they are considered to be restricted forever :type until_date: :obj:`int` or :obj:`datetime` - :param can_send_messages: Pass True, if the user can send text messages, contacts, locations and venues + :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` - :param can_send_media_messages: Pass True, if the user can send audios, documents, photos, videos, video notes - and voice notes, implies can_send_messages + :param can_send_media_messages: deprecated :type can_send_media_messages: :obj:`bool` - :param can_send_polls: Pass True, if the user is allowed to send polls, implies can_send_messages + :param can_send_polls: deprecated :type can_send_polls: :obj:`bool` - :param can_send_other_messages: Pass True, if the user can send animations, games, stickers and use inline bots, implies can_send_media_messages + :param can_send_other_messages: deprecated :type can_send_other_messages: :obj:`bool` - :param can_add_web_page_previews: Pass True, if the user may add web page previews to their messages, - implies can_send_media_messages + :param can_add_web_page_previews: deprecated :type can_add_web_page_previews: :obj:`bool` - :param can_change_info: Pass True, if the user is allowed to change the chat title, photo and other settings. - Ignored in public supergroups + :param can_change_info: deprecated :type can_change_info: :obj:`bool` - :param can_invite_users: Pass True, if the user is allowed to invite new users to the chat, - implies can_invite_users + :param can_invite_users: deprecated :type can_invite_users: :obj:`bool` - :param can_pin_messages: Pass True, if the user is allowed to pin messages. Ignored in public supergroups + :param can_pin_messages: deprecated :type can_pin_messages: :obj:`bool` - :param use_independent_chat_permissions: Pass True if chat permissions are set independently. Otherwise, - the can_send_other_messages and can_add_web_page_previews permissions will imply the can_send_messages, - can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and - can_send_voice_notes permissions; the can_send_polls permission will imply the can_send_messages permission. - :type use_independent_chat_permissions: :obj:`bool` + :param use_independent_chat_permissions: Optional Pass True if chat permissions are set independently. + Otherwise, the can_send_other_messages and can_add_web_page_previews permissions will imply the can_send_messages, + can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and can_send_voice_notes + permissions; the can_send_polls permission will imply the can_send_messages permission. - :param permissions: Pass ChatPermissions object to set all permissions at once. Use this param instead of - passing all boolean parameters. + :param permissions: ChatPermissions object defining permissions. :type permissions: :class:`telebot.types.ChatPermissions` :return: True on success :rtype: :obj:`bool` """ if permissions is None: + logger.warning('The parameters "can_..." are deprecated, use "permissions" instead.') permissions = types.ChatPermissions( can_send_messages=can_send_messages, can_send_media_messages=can_send_media_messages, @@ -3599,7 +3594,6 @@ def restrict_chat_member( can_invite_users=can_invite_users, can_pin_messages=can_pin_messages ) - logger.warning('The parameters "can_..." are deprecated, use "permissions" instead.') return apihelper.restrict_chat_member( self.token, chat_id, user_id, permissions, until_date=until_date, @@ -5242,8 +5236,8 @@ def edit_message_caption( def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message: """ - Convenience function for `send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs)` - + Convenience function for `send_message(message.chat.id, text, reply_parameters=(message.message_id...), **kwargs)` + :param message: Instance of :class:`telebot.types.Message` :type message: :obj:`types.Message` @@ -5255,7 +5249,18 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ - return self.send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs) + if "reply_parameters" in kwargs: + reply_parameters = kwargs["reply_parameters"] + else: + reply_parameters = None + if not reply_parameters: + reply_parameters = types.ReplyParameters(message.message_id) + + if "allow_sending_without_reply" in kwargs: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + reply_parameters.allow_sending_without_reply = kwargs.pop("allow_sending_without_reply") + + return self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) def answer_inline_query( diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 5a2376dfe..599874820 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1473,11 +1473,9 @@ def send_invoice( :param send_phone_number_to_provider: Pass True, if user's phone number should be sent to provider :param send_email_to_provider: Pass True, if user's email address should be sent to provider :param disable_notification: Sends the message silently. Users will receive a notification with no sound. - :param reply_to_message_id: If the message is a reply, ID of the original message :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button :param provider_data: A JSON-serialized data about the invoice, which will be shared with the payment provider. A detailed description of required fields should be provided by the payment provider. :param timeout: - :param allow_sending_without_reply: :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency :param suggested_tip_amounts: A JSON-serialized array of suggested amounts of tips in the smallest units of the currency. At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 2adf4275c..d783bfc0a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4608,39 +4608,34 @@ async def restrict_chat_member( they are considered to be restricted forever :type until_date: :obj:`int` or :obj:`datetime` - :param can_send_messages: Pass True, if the user can send text messages, contacts, locations and venues + :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` - :param can_send_media_messages: Pass True, if the user can send audios, documents, photos, videos, video notes - and voice notes, implies can_send_messages + :param can_send_media_messages: deprecated :type can_send_media_messages: :obj:`bool` - :param can_send_polls: Pass True, if the user is allowed to send polls, implies can_send_messages + :param can_send_polls: deprecated :type can_send_polls: :obj:`bool` - :param can_send_other_messages: Pass True, if the user can send animations, games, stickers and use inline bots, implies can_send_media_messages + :param can_send_other_messages: deprecated :type can_send_other_messages: :obj:`bool` - :param can_add_web_page_previews: Pass True, if the user may add web page previews to their messages, - implies can_send_media_messages + :param can_add_web_page_previews: deprecated :type can_add_web_page_previews: :obj:`bool` - :param can_change_info: Pass True, if the user is allowed to change the chat title, photo and other settings. - Ignored in public supergroups + :param can_change_info: deprecated :type can_change_info: :obj:`bool` - :param can_invite_users: Pass True, if the user is allowed to invite new users to the chat, - implies can_invite_users + :param can_invite_users: deprecated :type can_invite_users: :obj:`bool` - :param can_pin_messages: Pass True, if the user is allowed to pin messages. Ignored in public supergroups + :param can_pin_messages: deprecated :type can_pin_messages: :obj:`bool` - :param use_independent_chat_permissions: Pass True if chat permissions are set independently. Otherwise, - the can_send_other_messages and can_add_web_page_previews permissions will imply the can_send_messages, - can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and - can_send_voice_notes permissions; the can_send_polls permission will imply the can_send_messages permission. - :type use_independent_chat_permissions: :obj:`bool` + :param use_independent_chat_permissions: Optional Pass True if chat permissions are set independently. + Otherwise, the can_send_other_messages and can_add_web_page_previews permissions will imply the can_send_messages, + can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and can_send_voice_notes + permissions; the can_send_polls permission will imply the can_send_messages permission. :param permissions: Pass ChatPermissions object to set all permissions at once. Use this parameter instead of passing all boolean parameters to avoid backward compatibility problems in future. @@ -6224,7 +6219,7 @@ async def edit_message_caption( async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message: """ - Convenience function for `send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs)` + Convenience function for `send_message(message.chat.id, text, reply_parameters=(message.message_id...), **kwargs)` :param message: Instance of :class:`telebot.types.Message` :type message: :obj:`types.Message` @@ -6237,7 +6232,18 @@ async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.M :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ - return await self.send_message(message.chat.id, text, reply_to_message_id=message.message_id, **kwargs) + if "reply_parameters" in kwargs: + reply_parameters = kwargs["reply_parameters"] + else: + reply_parameters = None + if not reply_parameters: + reply_parameters = types.ReplyParameters(message.message_id) + + if "allow_sending_without_reply" in kwargs: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") + reply_parameters.allow_sending_without_reply = kwargs.pop("allow_sending_without_reply") + + return await self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) async def answer_inline_query( self, inline_query_id: str, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index c7d4df835..2b6bc2ce3 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1463,11 +1463,9 @@ async def send_invoice( :param send_phone_number_to_provider: Pass True, if user's phone number should be sent to provider :param send_email_to_provider: Pass True, if user's email address should be sent to provider :param disable_notification: Sends the message silently. Users will receive a notification with no sound. - :param reply_to_message_id: If the message is a reply, ID of the original message :param reply_markup: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button :param provider_data: A JSON-serialized data about the invoice, which will be shared with the payment provider. A detailed description of required fields should be provided by the payment provider. :param timeout: - :param allow_sending_without_reply: :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency :param suggested_tip_amounts: A JSON-serialized array of suggested amounts of tips in the smallest units of the currency. At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount. diff --git a/telebot/types.py b/telebot/types.py index dce297af7..d8521411b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2226,9 +2226,9 @@ class ForceReply(JsonSerializable): 1-64 characters :type input_field_placeholder: :obj:`str` - :param selective: Optional. Use this parameter if you want to force reply from specific users only. Targets: 1) users - that are @mentioned in the text of the Message object; 2) if the bot's message is a reply (has reply_to_message_id), - sender of the original message. + :param selective: Optional. Use this parameter if you want to force reply from specific users only. Targets: 1) users + that are @mentioned in the text of the Message object; 2) if the bot's message is a reply to a message in the same + chat and forum topic, sender of the original message. :type selective: :obj:`bool` :return: Instance of the class @@ -2343,10 +2343,11 @@ class ReplyKeyboardMarkup(JsonSerializable): active; 1-64 characters :type input_field_placeholder: :obj:`str` - :param selective: Optional. Use this parameter if you want to show the keyboard to specific users only. Targets: 1) - users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply (has - reply_to_message_id), sender of the original message.Example: A user requests to change the bot's language, bot - replies to the request with a keyboard to select the new language. Other users in the group don't see the keyboard. + :param selective: Optional. Use this parameter if you want to show the keyboard to specific users only. Targets: + 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply to a message + in the same chat and forum topic, sender of the original message. Example: A user requests to change the bot's + language, bot replies to the request with a keyboard to select the new language. Other users in the group don't + see the keyboard. :type selective: :obj:`bool` :param is_persistent: Optional. Use this parameter if you want to show the keyboard to specific users only. @@ -3424,7 +3425,7 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): def de_json(cls, json_string): if json_string is None: return json_string obj = cls.check_json(json_string, dict_copy=False) - return cls(**obj) + return cls(**obj, de_json = True) def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send_audios=None, can_send_documents=None, can_send_photos=None, @@ -3448,7 +3449,9 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send self.can_send_video_notes: bool = can_send_video_notes self.can_send_voice_notes: bool = can_send_voice_notes - if can_send_media_messages is not None: + if kwargs.get("de_json", False) and can_send_media_messages is not None: + # Telegram passes can_send_media_messages in Chat.permissions. Temporary created parameter "de_json" allows avoid + # deprection warning and individual parameters overriding. logger.warning('The parameter "can_send_media_messages" is deprecated. Use individual parameters like "can_send_audios", "can_send_documents" etc.') self.can_send_audios = can_send_media_messages self.can_send_documents = can_send_media_messages From aacfc9e938e585817e505550b7f15d79d3a0155b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 3 Feb 2024 20:36:55 +0300 Subject: [PATCH 140/480] Better process kwargs in reply_to --- telebot/__init__.py | 4 ++-- telebot/async_telebot.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 0c7ef6e22..188f2e853 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5249,8 +5249,8 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ - if "reply_parameters" in kwargs: - reply_parameters = kwargs["reply_parameters"] + if kwargs: + reply_parameters = kwargs.pop("reply_parameters", None) else: reply_parameters = None if not reply_parameters: diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d783bfc0a..37e07ef22 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6232,8 +6232,8 @@ async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.M :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ - if "reply_parameters" in kwargs: - reply_parameters = kwargs["reply_parameters"] + if kwargs: + reply_parameters = kwargs.pop("reply_parameters", None) else: reply_parameters = None if not reply_parameters: From 19f5c054d5628540623cf89708067a4bc02de742 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 3 Feb 2024 21:58:03 +0300 Subject: [PATCH 141/480] Fix allow_sending_without_reply in reply_to --- telebot/__init__.py | 19 +++++++++++-------- telebot/async_telebot.py | 17 ++++++++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 188f2e853..dbfca5642 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3472,7 +3472,7 @@ def ban_chat_member( less than 30 seconds from the current time they are considered to be banned forever :type until_date: :obj:`int` or :obj:`datetime` - :param revoke_messages: Bool: Pass True to delete all messages from the chat for the user that is being removed. + :param revoke_messages: Pass True to delete all messages from the chat for the user that is being removed. If False, the user will be able to see messages in the group that were sent before the user was removed. Always True for supergroups and channels. :type revoke_messages: :obj:`bool` @@ -3545,7 +3545,7 @@ def restrict_chat_member( :param until_date: Date when restrictions will be lifted for the user, unix time. If user is restricted for more than 366 days or less than 30 seconds from the current time, they are considered to be restricted forever - :type until_date: :obj:`int` or :obj:`datetime` + :type until_date: :obj:`int` or :obj:`datetime`, optional :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` @@ -3571,10 +3571,11 @@ def restrict_chat_member( :param can_pin_messages: deprecated :type can_pin_messages: :obj:`bool` - :param use_independent_chat_permissions: Optional Pass True if chat permissions are set independently. + :param use_independent_chat_permissions: Pass True if chat permissions are set independently. Otherwise, the can_send_other_messages and can_add_web_page_previews permissions will imply the can_send_messages, can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and can_send_voice_notes permissions; the can_send_polls permission will imply the can_send_messages permission. + :type use_independent_chat_permissions: :obj:`bool`, optional :param permissions: ChatPermissions object defining permissions. :type permissions: :class:`telebot.types.ChatPermissions` @@ -5251,14 +5252,16 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message """ if kwargs: reply_parameters = kwargs.pop("reply_parameters", None) + if "allow_sending_without_reply" in kwargs: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") else: reply_parameters = None - if not reply_parameters: - reply_parameters = types.ReplyParameters(message.message_id) - if "allow_sending_without_reply" in kwargs: - logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - reply_parameters.allow_sending_without_reply = kwargs.pop("allow_sending_without_reply") + if not reply_parameters: + reply_parameters = types.ReplyParameters( + message.message_id, + allow_sending_without_reply=kwargs.pop("allow_sending_without_reply", None) if kwargs else None + ) return self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 37e07ef22..dcf947a52 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4606,7 +4606,7 @@ async def restrict_chat_member( :param until_date: Date when restrictions will be lifted for the user, unix time. If user is restricted for more than 366 days or less than 30 seconds from the current time, they are considered to be restricted forever - :type until_date: :obj:`int` or :obj:`datetime` + :type until_date: :obj:`int` or :obj:`datetime`, optional :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` @@ -4632,10 +4632,11 @@ async def restrict_chat_member( :param can_pin_messages: deprecated :type can_pin_messages: :obj:`bool` - :param use_independent_chat_permissions: Optional Pass True if chat permissions are set independently. + :param use_independent_chat_permissions: Pass True if chat permissions are set independently. Otherwise, the can_send_other_messages and can_add_web_page_previews permissions will imply the can_send_messages, can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and can_send_voice_notes permissions; the can_send_polls permission will imply the can_send_messages permission. + :type use_independent_chat_permissions: :obj:`bool`, optional :param permissions: Pass ChatPermissions object to set all permissions at once. Use this parameter instead of passing all boolean parameters to avoid backward compatibility problems in future. @@ -6234,14 +6235,16 @@ async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.M """ if kwargs: reply_parameters = kwargs.pop("reply_parameters", None) + if "allow_sending_without_reply" in kwargs: + logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") else: reply_parameters = None - if not reply_parameters: - reply_parameters = types.ReplyParameters(message.message_id) - if "allow_sending_without_reply" in kwargs: - logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - reply_parameters.allow_sending_without_reply = kwargs.pop("allow_sending_without_reply") + if not reply_parameters: + reply_parameters = types.ReplyParameters( + message.message_id, + allow_sending_without_reply=kwargs.pop("allow_sending_without_reply", None) if kwargs else None + ) return await self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) From 08c7ccef7e3403e4be1bab02cc6b694d3c685813 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 4 Feb 2024 15:08:55 +0400 Subject: [PATCH 142/480] Create pyproject.toml --- pyproject.toml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..4b04cc3de --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,49 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "pyTelegramBotAPI" +version = "4.15.4" +description = "Python Telegram bot api." +authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] +license = {text = "GPL2"} +readme = "README.md" +requires-python = ">=3.7" +keywords = ["telegram", "bot", "api", "tools"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Environment :: Console", + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)" +] +dependencies = ["requests"] + +[project.urls] +Homepage = "https://github.com/eternnoir/pyTelegramBotAPI" +Documentation = "https://pytba.readthedocs.org" +Repository = "https://github.com/eternnoir/pyTelegramBotAPI" +Issues = "https://github.com/eternnoir/pyTelegramBotAPI/issues" + + +[project.optional-dependencies] +json = ["ujson"] +PIL = ["Pillow"] +redis = ["redis>=3.4.1"] +aioredis = ["aioredis"] +aiohttp = ["aiohttp"] +fastapi = ["fastapi"] +uvicorn = ["uvicorn"] +psutil = ["psutil"] +coloredlogs = ["coloredlogs"] +watchdog = ["watchdog"] + + +[tool.hatch.build.targets.wheel] +package = ["telebot"] From 0d2b886ab70d51ea8eecb8a54443c5eaaa9bacb7 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 4 Feb 2024 15:09:06 +0400 Subject: [PATCH 143/480] Delete setup.py --- setup.py | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 setup.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 5180f5623..000000000 --- a/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -from setuptools import setup, find_packages -from io import open -import re - -def read(filename): - with open(filename, encoding='utf-8') as file: - return file.read() - -with open('telebot/version.py', 'r', encoding='utf-8') as f: # Credits: LonamiWebs - version = re.search(r"^__version__\s*=\s*'(.*)'.*$", - f.read(), flags=re.MULTILINE).group(1) - -setup(name='pyTelegramBotAPI', - version=version, - description='Python Telegram bot api. ', - long_description=read('README.md'), - long_description_content_type="text/markdown", - author='eternnoir', - author_email='eternnoir@gmail.com', - url='https://github.com/eternnoir/pyTelegramBotAPI', - packages = find_packages(exclude = ['tests', 'examples']), - license='GPL2', - keywords='telegram bot api tools', - install_requires=['requests'], - extras_require={ - 'json': 'ujson', - 'PIL': 'Pillow', - 'redis': 'redis>=3.4.1', - 'aioredis': 'aioredis', - 'aiohttp': 'aiohttp', - 'fastapi': 'fastapi', - 'uvicorn': 'uvicorn', - 'psutil': 'psutil', - 'coloredlogs': 'coloredlogs', - 'watchdog': 'watchdog' - }, - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Programming Language :: Python :: 3', - 'Environment :: Console', - 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', - ], - - ) From 0998c36f20183b44ed5edd384bdc104af7b72005 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 4 Feb 2024 15:10:35 +0400 Subject: [PATCH 144/480] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4b04cc3de..66eeabca5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,4 +46,4 @@ watchdog = ["watchdog"] [tool.hatch.build.targets.wheel] -package = ["telebot"] +include = ["telebot/*"] From f49b34b54da490e8e478e9399e87bdf1eb50fce7 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 4 Feb 2024 15:17:52 +0400 Subject: [PATCH 145/480] Update setup_python.yml --- .github/workflows/setup_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index 2a9787e25..d21a08ce7 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -31,5 +31,5 @@ jobs: architecture: x64 - run: | pip3 install -r requirements.txt - python setup.py install + pip3 install . cd tests && py.test From 8771f408dd78bb033d865cf5d74492b66c4ff192 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 4 Feb 2024 15:19:14 +0400 Subject: [PATCH 146/480] Update aiohttp to support python 3.12 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fdbff1c63..049b84f84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest requests==2.31.0 wheel==0.38.1 -aiohttp>=3.8.0,<3.9.0 \ No newline at end of file +aiohttp==3.9.0 From d8b4dcce9ae3c291e9f02cd6d69defa60fab977d Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 4 Feb 2024 15:19:40 +0400 Subject: [PATCH 147/480] add tests for python 3.12 --- .github/workflows/setup_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index d21a08ce7..5518ff2f3 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] name: ${{ matrix.python-version }} and tests steps: - uses: actions/checkout@v2 From 018cc660f18b09e3f497c3f3c1a3026cac260d8a Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 8 Feb 2024 18:17:26 +0300 Subject: [PATCH 148/480] One more fix for BoostSource --- telebot/types.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index d8521411b..c92775890 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9055,11 +9055,11 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - user = User.de_json(obj['user']) - return cls(user) + obj['user'] = User.de_json(obj['user']) + return cls(**obj) - def __init__(self, user): - super().__init__('premium') + def __init__(self, source, user, **kwargs): + self.source = source self.user = user @@ -9085,11 +9085,11 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - user = User.de_json(obj['user']) - return cls(user) + obj['user'] = User.de_json(obj['user']) + return cls(**obj) - def __init__(self, user): - super().__init__('gift_code') + def __init__(self, source, user, **kwargs): + self.source = source self.user = user @@ -9121,11 +9121,11 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - user = User.de_json(obj['user']) if 'user' in obj else None - return cls(obj['giveaway_message_id'], user, obj.get('is_unclaimed')) + obj['user'] = User.de_json(obj['user']) + return cls(**obj) - def __init__(self, giveaway_message_id, user=None, is_unclaimed=None): - super().__init__('giveaway') + def __init__(self, source, giveaway_message_id, user=None, is_unclaimed=None, **kwargs): + self.source = source self.giveaway_message_id = giveaway_message_id self.user = user self.is_unclaimed = is_unclaimed From cf323fc5441c3645470a28c3bc59142aba31436d Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 8 Feb 2024 23:46:41 +0300 Subject: [PATCH 149/480] ChatBoost protect from errors --- telebot/types.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index c92775890..326c172f9 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9158,6 +9158,18 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + if not 'boost_id' in obj: + # Suppose that the field "boost_id" is not always provided by Telegram + logger.warning('The field "boost_id" is not found in received ChatBoost.') + obj['boost_id'] = None + if not 'add_date' in obj: + # Suppose that the field "boost_id" is not always provided by Telegram + logger.warning('The field "add_date" is not found in received ChatBoost.') + obj['add_date'] = None + if not 'expiration_date' in obj: + # Suppose that the field "boost_id" is not always provided by Telegram + logger.warning('The field "expiration_date" is not found in received ChatBoost.') + obj['expiration_date'] = None source = obj.get('source', None) obj['source'] = ChatBoostSource.de_json(source) if source else None return cls(**obj) @@ -9191,7 +9203,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, boosts, **kwargs): - self.boosts: ChatBoost = boosts + self.boosts: List[ChatBoost] = boosts class InaccessibleMessage(JsonDeserializable): From bd315963e1b3c5ff8a1ea3ce5c60e52e46baaf69 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 13 Feb 2024 22:25:50 +0400 Subject: [PATCH 150/480] Update types.py --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 326c172f9..9d065086e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -204,7 +204,7 @@ def de_json(cls, json_string): message_reaction = MessageReactionUpdated.de_json(obj.get('message_reaction')) message_reaction_count = MessageReactionCountUpdated.de_json(obj.get('message_reaction_count')) removed_chat_boost = ChatBoostRemoved.de_json(obj.get('removed_chat_boost')) - chat_boost = ChatBoost.de_json(obj.get('chat_boost')) + chat_boost = ChatBoostUpdated.de_json(obj.get('chat_boost')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost) From b9291cbe885690b19d5efcdd1357304a64399798 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 13 Feb 2024 22:38:46 +0400 Subject: [PATCH 151/480] Added typehints for recent bot api 7.0 --- telebot/types.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 9d065086e..2a86de5b8 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8961,8 +8961,8 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, chat, boost, **kwargs): - self.chat = chat - self.boost = boost + self.chat: Chat = chat + self.boost: ChatBoost = boost class ChatBoostRemoved(JsonDeserializable): @@ -8997,10 +8997,10 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, chat, boost_id, remove_date, source, **kwargs): - self.chat = chat - self.boost_id = boost_id - self.remove_date = remove_date - self.source = source + self.chat: Chat = chat + self.boost_id: str = boost_id + self.remove_date: int = remove_date + self.source: ChatBoostSource = source class ChatBoostSource(ABC, JsonDeserializable): @@ -9059,8 +9059,8 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, source, user, **kwargs): - self.source = source - self.user = user + self.source: str = source + self.user: User = user # noinspection PyUnresolvedReferences @@ -9089,8 +9089,8 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, source, user, **kwargs): - self.source = source - self.user = user + self.source: str = source + self.user: User = user # noinspection PyUnresolvedReferences @@ -9125,10 +9125,10 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, source, giveaway_message_id, user=None, is_unclaimed=None, **kwargs): - self.source = source - self.giveaway_message_id = giveaway_message_id - self.user = user - self.is_unclaimed = is_unclaimed + self.source: str = source + self.giveaway_message_id: int = giveaway_message_id + self.user: User = user + self.is_unclaimed: bool = is_unclaimed class ChatBoost(JsonDeserializable): @@ -9175,9 +9175,9 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, boost_id, add_date, expiration_date, source, **kwargs): - self.boost_id = boost_id - self.add_date = add_date - self.expiration_date = expiration_date + self.boost_id: str = boost_id + self.add_date: int = add_date + self.expiration_date: int = expiration_date self.source: ChatBoostSource = source @@ -9234,9 +9234,9 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, chat, message_id, date, **kwargs): - self.chat = chat - self.message_id = message_id - self.date = date + self.chat: Chat = chat + self.message_id: int = message_id + self.date: int = date @staticmethod def __universal_deprecation(property_name): From 89bfd038991dca778707e6e7388b89998e86fdf3 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 16 Feb 2024 16:43:11 +0300 Subject: [PATCH 152/480] Bump version to 4.15.5 --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b4369c1c2..540a0ccf2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.15.4' +release = '4.15.5' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 66eeabca5..b6f8625e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.15.4" +version = "4.15.5" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 1e29eda03..5edc33436 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.15.4' +__version__ = '4.15.5' From 4c4c198fc3985a038b9136dd94df12bf6a7ac1ed Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 16 Feb 2024 17:19:57 +0300 Subject: [PATCH 153/480] Fix python versions 3.8-3.12 --- .travis.yml | 1 + README.md | 2 +- pyproject.toml | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8e6b02e5c..1fe9399d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - "3.9" - "3.10" - "3.11" + - "3.12" - "pypy3" install: "pip install -r requirements.txt" script: diff --git a/README.md b/README.md index 289e38d7a..bcc07fa47 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ## Getting started -This API is tested with Python 3.8-3.11 and Pypy 3. +This API is tested with Python 3.8-3.12 and Pypy 3. There are two ways to install the library: * Installation using pip (a Python package manager): diff --git a/pyproject.toml b/pyproject.toml index b6f8625e3..729592cff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,12 +9,11 @@ description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.8" keywords = ["telegram", "bot", "api", "tools"] classifiers = [ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", From 0e125ab942e6a746549540d97dd0a49b8b1e78fb Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 16 Feb 2024 21:59:51 +0400 Subject: [PATCH 154/480] Added the class ChatBoostAdded and the field boost_added to the class Message for service messages about a user boosting a chat. --- telebot/types.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 2a86de5b8..8f467fdde 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1012,6 +1012,9 @@ class Message(JsonDeserializable): proximity alert while sharing Live Location. :type proximity_alert_triggered: :class:`telebot.types.ProximityAlertTriggered` + :param boost_added: Optional. Service message: user boosted the chat + :type boost_added: :class:`telebot.types.ChatBoostAdded` + :param forum_topic_created: Optional. Service message: forum topic created :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` @@ -1275,6 +1278,10 @@ def de_json(cls, json_string): content_type = 'giveaway_completed' if 'forward_origin' in obj: opts['forward_origin'] = MessageOrigin.de_json(obj['forward_origin']) + if 'boost_added' in obj: + opts['boost_added'] = ChatBoostAdded.de_json(obj['boost_added']) + content_type = 'boost_added' + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1375,6 +1382,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.giveaway_winners: Optional[GiveawayWinners] = None self.giveaway_completed: Optional[GiveawayCompleted] = None self.forward_origin: Optional[MessageOrigin] = None + self.boost_added: Optional[ChatBoostAdded] = None for key in options: setattr(self, key, options[key]) @@ -9262,3 +9270,27 @@ def __getattr__(self, item): return self.__universal_deprecation(item) else: raise AttributeError(f'"{self.__class__.__name__}" object has no attribute "{item}"') + + +class ChatBoostAdded(JsonDeserializable): + """ + This object represents a service message about a user boosting a chat. + + Telegram documentation: https://core.telegram.org/bots/api#chatboostadded + + :param boost_count: Number of boosts added by the user + :type boost_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`ChatBoostAdded` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, boost_count, **kwargs): + self.boost_count: int = boost_count From f5477d76b78c0daa0b43c9f9773f74d087308a50 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 16 Feb 2024 22:02:21 +0400 Subject: [PATCH 155/480] Added the field sender_boost_count to the class Message. --- telebot/types.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 8f467fdde..08a9760db 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -805,6 +805,9 @@ class Message(JsonDeserializable): fake sender user in non-channel chats, if the message was sent on behalf of a chat. :type sender_chat: :class:`telebot.types.Chat` + :param sender_boost_count: Optional. If the sender of the message boosted the chat, the number of boosts added by the user + :type sender_boost_count: :obj:`int` + :param date: Date the message was sent in Unix time :type date: :obj:`int` @@ -1281,6 +1284,8 @@ def de_json(cls, json_string): if 'boost_added' in obj: opts['boost_added'] = ChatBoostAdded.de_json(obj['boost_added']) content_type = 'boost_added' + if 'sender_boost_count' in obj: + opts['sender_boost_count'] = obj['sender_boost_count'] return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1383,6 +1388,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.giveaway_completed: Optional[GiveawayCompleted] = None self.forward_origin: Optional[MessageOrigin] = None self.boost_added: Optional[ChatBoostAdded] = None + self.sender_boost_count: Optional[int] = None for key in options: setattr(self, key, options[key]) From 86285a67fbbb0d5e9f031e27d763709866fda731 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 16 Feb 2024 22:04:17 +0400 Subject: [PATCH 156/480] Added the field reply_to_story to the class Message. --- telebot/types.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 08a9760db..68a11a17c 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -853,6 +853,9 @@ class Message(JsonDeserializable): :param quote: Optional. For replies that quote part of the original message, the quoted part of the message :type quote: :class:`telebot.types.TextQuote` + :param reply_to_story: Optional. For replies to a story, the original story + :type reply_to_story: :class:`telebot.types.Story` + :param via_bot: Optional. Bot through which the message was sent :type via_bot: :class:`telebot.types.User` @@ -1286,6 +1289,8 @@ def de_json(cls, json_string): content_type = 'boost_added' if 'sender_boost_count' in obj: opts['sender_boost_count'] = obj['sender_boost_count'] + if 'reply_to_story' in obj: + opts['reply_to_story'] = Story.de_json(obj['reply_to_story']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1389,6 +1394,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.forward_origin: Optional[MessageOrigin] = None self.boost_added: Optional[ChatBoostAdded] = None self.sender_boost_count: Optional[int] = None + self.reply_to_story: Optional[Story] = None for key in options: setattr(self, key, options[key]) From 1eceda12b1271f89bff783e776eb7069eb601bd1 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 16 Feb 2024 22:06:27 +0400 Subject: [PATCH 157/480] Added the fields chat and id to the class Story. --- telebot/types.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 68a11a17c..8b9dfc2bb 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8063,8 +8063,18 @@ def to_json(self) -> str: class Story(JsonDeserializable): """ - This object represents a message about a forwarded story in the chat. - Currently holds no information. + This object represents a story. + + Telegram documentation: https://core.telegram.org/bots/api#story + + :param chat: Chat that posted the story + :type chat: :class:`telebot.types.Chat` + + :param id: Unique identifier for the story in the chat + :type id: :obj:`int` + + :return: Instance of the class + :rtype: :class:`Story` """ @classmethod @@ -8072,10 +8082,12 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) - - def __init__(self, **kwargs) -> None: - pass + + def __init__(self, chat: Chat, id: int, **kwargs) -> None: + self.chat: Chat = chat + self.id: int = id # base class From 8386a596b7db4e112df761746caacb0d4cabf738 Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 16 Feb 2024 22:12:47 +0400 Subject: [PATCH 158/480] Added the field unrestrict_boost_count to the class Chat. --- telebot/types.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 8b9dfc2bb..79e875fc4 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -625,6 +625,10 @@ class Chat(JsonDeserializable): by each unpriviledged user; in seconds. Returned only in getChat. :type slow_mode_delay: :obj:`int` + :param unrestrict_boost_count: Optional. For supergroups, the minimum number of boosts that a non-administrator + user needs to add in order to ignore slow mode and chat permissions. Returned only in getChat. + :type unrestrict_boost_count: :obj:`int` + :param message_auto_delete_time: Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in getChat. :type message_auto_delete_time: :obj:`int` @@ -691,7 +695,8 @@ def __init__(self, id, type, title=None, username=None, first_name=None, is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, - profile_background_custom_emoji_id=None, has_visible_history=None, **kwargs): + profile_background_custom_emoji_id=None, has_visible_history=None, + unrestrict_boost_count=None,**kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -727,6 +732,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.profile_accent_color_id: int = profile_accent_color_id self.profile_background_custom_emoji_id: str = profile_background_custom_emoji_id self.has_visible_history: bool = has_visible_history + self.unrestrict_boost_count: int = unrestrict_boost_count From 9c5e3d6e205a2097bff0900b14c4eeefa025205a Mon Sep 17 00:00:00 2001 From: coder2020official Date: Fri, 16 Feb 2024 22:14:20 +0400 Subject: [PATCH 159/480] Added the field custom_emoji_sticker_set_name to the class Chat. --- telebot/types.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 79e875fc4..fe1285bc2 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -656,6 +656,10 @@ class Chat(JsonDeserializable): getChat. :type can_set_sticker_set: :obj:`bool` + :param custom_emoji_sticker_set_name: Optional. For supergroups, the name of the group's custom emoji sticker set. + Custom emoji from this set can be used by all users and bots in the group. Returned only in getChat. + :param custom_emoji_sticker_set_name: :obj:`str` + :param linked_chat_id: Optional. Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; for supergroups and channel chats. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a @@ -696,7 +700,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, profile_background_custom_emoji_id=None, has_visible_history=None, - unrestrict_boost_count=None,**kwargs): + unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -733,6 +737,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.profile_background_custom_emoji_id: str = profile_background_custom_emoji_id self.has_visible_history: bool = has_visible_history self.unrestrict_boost_count: int = unrestrict_boost_count + self.custom_emoji_sticker_set_name: str = custom_emoji_sticker_set_name From 9c1b2489df8c895beeb5381fff1f1c5256ffdb80 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 16 Feb 2024 22:20:40 +0400 Subject: [PATCH 160/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bcc07fa47..470127a49 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.0! +##

Supported Bot API version: 7.1!

Official documentation

Official ru documentation

From 0de74806763e53e6c7d6f215e60ced79e67212c9 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Feb 2024 15:43:20 +0300 Subject: [PATCH 161/480] Fix ChatBoostSourceGiveaway and bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/types.py | 2 +- telebot/version.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 540a0ccf2..dd00ce713 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.15.5' +release = '4.16.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 729592cff..7026a1345 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.15.5" +version = "4.16.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/types.py b/telebot/types.py index fe1285bc2..03516d4b9 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9164,7 +9164,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - obj['user'] = User.de_json(obj['user']) + obj['user'] = User.de_json(obj.get('user')) return cls(**obj) def __init__(self, source, giveaway_message_id, user=None, is_unclaimed=None, **kwargs): diff --git a/telebot/version.py b/telebot/version.py index 5edc33436..2e13bf898 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.15.5' +__version__ = '4.16.0' From 3ea992447b4a35560e67b872d1712671ea16999e Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Feb 2024 16:20:00 +0300 Subject: [PATCH 162/480] Fix GiveawayCreated not implemented --- telebot/types.py | 100 +++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 60 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 03516d4b9..3451448d0 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -173,7 +173,7 @@ class Update(JsonDeserializable): :type chat_join_request: :class:`telebot.types.ChatJoinRequest` :param chat_boost: Optional. A chat boost was added or changed. The bot must be an administrator in the chat to receive these updates. - :type chat_boost: :class:`telebot.types.ChatBoost` + :type chat_boost: :class:`telebot.types.ChatBoostUpdated` :param removed_chat_boost: Optional. A chat boost was removed. The bot must be an administrator in the chat to receive these updates. :type removed_chat_boost: :class:`telebot.types.RemovedChatBoost` @@ -3454,7 +3454,7 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): """ @classmethod def de_json(cls, json_string): - if json_string is None: return json_string + if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj, de_json = True) @@ -7050,7 +7050,7 @@ class ChatLocation(JsonSerializable, JsonDeserializable, Dictionaryable): """ @classmethod def de_json(cls, json_string): - if json_string is None: return json_string + if json_string is None: return None obj = cls.check_json(json_string) obj['location'] = Location.de_json(obj['location']) return cls(**obj) @@ -7967,8 +7967,7 @@ class SwitchInlineQueryChosenChat(JsonDeserializable, Dictionaryable, JsonSerial @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) @@ -8015,8 +8014,7 @@ class BotName(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) @@ -8090,8 +8088,7 @@ class Story(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) @@ -8117,8 +8114,7 @@ class ReactionType(JsonDeserializable, Dictionaryable, JsonSerializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) # remove type if obj['type'] == 'emoji': @@ -8228,8 +8224,7 @@ class MessageReactionUpdated(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) @@ -8277,8 +8272,7 @@ class MessageReactionCountUpdated(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['reactions'] = [ReactionCount.de_json(reaction) for reaction in obj['reactions']] @@ -8309,8 +8303,7 @@ class ReactionCount(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['type'] = ReactionType.de_json(obj['type']) return cls(**obj) @@ -8401,8 +8394,7 @@ class ExternalReplyInfo(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['origin'] = MessageOrigin.de_json(obj['origin']) if 'chat' in obj: @@ -8514,8 +8506,7 @@ class MessageOrigin(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) message_type = obj['type'] if message_type == 'user': @@ -8626,8 +8617,7 @@ class LinkPreviewOptions(JsonDeserializable, Dictionaryable, JsonSerializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) @@ -8695,8 +8685,7 @@ class Giveaway(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chats'] = [Chat.de_json(chat) for chat in obj['chats']] return cls(**obj) @@ -8760,8 +8749,7 @@ class GiveawayWinners(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['winners'] = [User.de_json(user) for user in obj['winners']] @@ -8806,8 +8794,7 @@ class GiveawayCompleted(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) if 'giveaway_message' in obj: obj['giveaway_message'] = Message.de_json(obj['giveaway_message']) @@ -8824,8 +8811,17 @@ class GiveawayCreated(JsonDeserializable): """ This object represents a service message about the creation of a scheduled giveaway. Currently holds no information. """ - - + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, **kwargs) -> None: + pass + + class TextQuote(JsonDeserializable): """ This object contains information about the quoted part of a message that is replied to by the given message. @@ -8850,8 +8846,7 @@ class TextQuote(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) if 'entities' in obj: obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] @@ -8899,8 +8894,7 @@ class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) if 'quote_entities' in obj: obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj['quote_entities']] @@ -8963,8 +8957,7 @@ class UsersShared(JsonDeserializable): """ @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) @@ -8996,8 +8989,7 @@ class ChatBoostUpdated(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['boost'] = ChatBoost.de_json(obj['boost']) @@ -9032,8 +9024,7 @@ class ChatBoostRemoved(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['source'] = ChatBoostSource.de_json(obj['source']) @@ -9055,17 +9046,13 @@ class ChatBoostSource(ABC, JsonDeserializable): Telegram documentation: https://core.telegram.org/bots/api#chatboostsource - :param source: Source of the boost - :type source: :obj:`str` - :return: Instance of the class :rtype: :class:`ChatBoostSourcePremium` or :class:`ChatBoostSourceGiftCode` or :class:`ChatBoostSourceGiveaway` """ @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) if obj["source"] == "premium": return ChatBoostSourcePremium.de_json(obj) @@ -9095,8 +9082,7 @@ class ChatBoostSourcePremium(ChatBoostSource): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) return cls(**obj) @@ -9125,8 +9111,7 @@ class ChatBoostSourceGiftCode(ChatBoostSource): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) return cls(**obj) @@ -9161,8 +9146,7 @@ class ChatBoostSourceGiveaway(ChatBoostSource): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj.get('user')) return cls(**obj) @@ -9198,8 +9182,7 @@ class ChatBoost(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) if not 'boost_id' in obj: # Suppose that the field "boost_id" is not always provided by Telegram @@ -9239,8 +9222,7 @@ class UserChatBoosts(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['boosts'] = [ChatBoost.de_json(boost) for boost in obj['boosts']] return cls(**obj) @@ -9270,8 +9252,7 @@ class InaccessibleMessage(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) @@ -9322,8 +9303,7 @@ class ChatBoostAdded(JsonDeserializable): @classmethod def de_json(cls, json_string): - if json_string is None: - return None + if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) From 93eab1207079bb1a56c1607ea55d05f916b3d3d9 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Feb 2024 21:14:28 +0300 Subject: [PATCH 163/480] Readme fix + bump version --- README.md | 6 ------ docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 470127a49..adee76fc5 100644 --- a/README.md +++ b/README.md @@ -79,12 +79,6 @@ $ pip install pyTelegramBotAPI ``` * Installation from source (requires git): -``` -$ git clone https://github.com/eternnoir/pyTelegramBotAPI.git -$ cd pyTelegramBotAPI -$ python setup.py install -``` -or: ``` $ pip install git+https://github.com/eternnoir/pyTelegramBotAPI.git ``` diff --git a/docs/source/conf.py b/docs/source/conf.py index dd00ce713..c9edf448c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.16.0' +release = '4.16.1' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 7026a1345..68f0254ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.16.0" +version = "4.16.1" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 2e13bf898..0b4b31ee0 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.16.0' +__version__ = '4.16.1' From 224b0db6fe703fc18684f8679df7cfdf0eadde20 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 18 Feb 2024 09:24:22 +0300 Subject: [PATCH 164/480] MenuButton set default types --- telebot/types.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 3451448d0..222048cfc 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7279,8 +7279,7 @@ class VideoChatParticipantsInvited(JsonDeserializable): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - if 'users' in obj: - obj['users'] = [User.de_json(u) for u in obj['users']] + obj['users'] = [User.de_json(u) for u in obj['users']] return cls(**obj) def __init__(self, users=None, **kwargs): @@ -7366,8 +7365,8 @@ class MenuButtonCommands(MenuButton): :rtype: :class:`telebot.types.MenuButtonCommands` """ - def __init__(self, type, **kwargs): - self.type = type + def __init__(self, type = None, **kwargs): + self.type: str = "commands" def to_dict(self): return {'type': self.type} @@ -7397,7 +7396,7 @@ class MenuButtonWebApp(MenuButton): """ def __init__(self, type, text, web_app, **kwargs): - self.type: str = type + self.type: str = "web_app" self.text: str = text self.web_app: WebAppInfo = web_app @@ -7420,8 +7419,8 @@ class MenuButtonDefault(MenuButton): :return: Instance of the class :rtype: :class:`telebot.types.MenuButtonDefault` """ - def __init__(self, type, **kwargs): - self.type: str = type + def __init__(self, type = None, **kwargs): + self.type: str = "default" def to_dict(self): return {'type': self.type} From 61be27fd3a17555a65a29147b23486303ca4e898 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 24 Feb 2024 11:26:43 +0300 Subject: [PATCH 165/480] Allow to pass no message_id to bot.reply_to --- telebot/__init__.py | 3 +++ telebot/async_telebot.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index dbfca5642..54716eac2 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5263,6 +5263,9 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message allow_sending_without_reply=kwargs.pop("allow_sending_without_reply", None) if kwargs else None ) + if not reply_parameters.message_id: + reply_parameters.message_id = message.message_id + return self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index dcf947a52..8ae599e6a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6246,6 +6246,9 @@ async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.M allow_sending_without_reply=kwargs.pop("allow_sending_without_reply", None) if kwargs else None ) + if not reply_parameters.message_id: + reply_parameters.message_id = message.message_id + return await self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) async def answer_inline_query( From 62244c68168ea02b4b295ed2c56369da3d27ef85 Mon Sep 17 00:00:00 2001 From: Jasmine Date: Tue, 27 Feb 2024 11:49:57 +0800 Subject: [PATCH 166/480] fix(hint): add_sticker_to_set -> sticker --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 54716eac2..37cd2e6df 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5710,7 +5710,7 @@ def add_sticker_to_set( tgs_sticker: Optional[Union[Any, str]]=None, webm_sticker: Optional[Union[Any, str]]=None, mask_position: Optional[types.MaskPosition]=None, - sticker: Optional[List[types.InputSticker]]=None) -> bool: + sticker: Optional[types.InputSticker]=None) -> bool: """ Use this method to add a new sticker to a set created by the bot. The format of the added sticker must match the format of the other stickers in the set. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8ae599e6a..a1e453d6d 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6689,7 +6689,7 @@ async def add_sticker_to_set( tgs_sticker: Optional[Union[Any, str]]=None, webm_sticker: Optional[Union[Any, str]]=None, mask_position: Optional[types.MaskPosition]=None, - sticker: Optional[List[types.InputSticker]]=None) -> bool: + sticker: Optional[types.InputSticker]=None) -> bool: """ Use this method to add a new sticker to a set created by the bot. The format of the added sticker must match the format of the other stickers in the set. From 7cab63984bbb94c08e6f4cba6612826c2ac4230c Mon Sep 17 00:00:00 2001 From: Jasmine Date: Tue, 27 Feb 2024 11:54:33 +0800 Subject: [PATCH 167/480] fix(comments) --- telebot/__init__.py | 4 ++-- telebot/async_telebot.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 37cd2e6df..55f264dfa 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5746,8 +5746,8 @@ def add_sticker_to_set( :param mask_position: A JSON-serialized object for position where the mask should be placed on faces :type mask_position: :class:`telebot.types.MaskPosition` - :param sticker: A JSON-serialized list of 1-50 initial stickers to be added to the sticker set - :type sticker: :obj:`list` of :class:`telebot.types.InputSticker` + :param sticker: A JSON-serialized object for stickers to be added to the sticker set + :type sticker: :class:`telebot.types.InputSticker` :return: On success, True is returned. :rtype: :obj:`bool` diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index a1e453d6d..6a0d5ab90 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6725,8 +6725,8 @@ async def add_sticker_to_set( :param mask_position: A JSON-serialized object for position where the mask should be placed on faces :type mask_position: :class:`telebot.types.MaskPosition` - :param sticker: A JSON-serialized list of 1-50 initial stickers to be added to the sticker set - :type sticker: :obj:`list` of :class:`telebot.types.InputSticker` + :param sticker: A JSON-serialized object for stickers to be added to the sticker set + :type sticker: :class:`telebot.types.InputSticker` :return: On success, True is returned. :rtype: :obj:`bool` From 112266d8dd916d9ada5965ab89179b685abb485d Mon Sep 17 00:00:00 2001 From: Jasmine Date: Tue, 27 Feb 2024 11:56:47 +0800 Subject: [PATCH 168/480] fix --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 55f264dfa..39a9c25aa 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5746,7 +5746,7 @@ def add_sticker_to_set( :param mask_position: A JSON-serialized object for position where the mask should be placed on faces :type mask_position: :class:`telebot.types.MaskPosition` - :param sticker: A JSON-serialized object for stickers to be added to the sticker set + :param sticker: A JSON-serialized object for sticker to be added to the sticker set :type sticker: :class:`telebot.types.InputSticker` :return: On success, True is returned. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 6a0d5ab90..fece7a2e7 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6725,7 +6725,7 @@ async def add_sticker_to_set( :param mask_position: A JSON-serialized object for position where the mask should be placed on faces :type mask_position: :class:`telebot.types.MaskPosition` - :param sticker: A JSON-serialized object for stickers to be added to the sticker set + :param sticker: A JSON-serialized object for sticker to be added to the sticker set :type sticker: :class:`telebot.types.InputSticker` :return: On success, True is returned. From a5927350bd92f339231e9de7afdef319cca1905f Mon Sep 17 00:00:00 2001 From: Hansana Dasanayaka <75363593+hansanaD@users.noreply.github.com> Date: Wed, 28 Feb 2024 09:58:28 +0530 Subject: [PATCH 169/480] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index adee76fc5..ad8d01fae 100644 --- a/README.md +++ b/README.md @@ -889,5 +889,6 @@ Here are some examples of template: * [QR-Code For You Bot](https://t.me/qrcode_for_you_bot) ([source](https://github.com/arashnm80/qrcode-for-you-bot)) by [Arashnm80](https://github.com/arashnm80). Telegram qrcode generator bot created with pyhton and telebot. * [Best Instagram Downloader Bot](https://t.me/Best_Instagram_Downloader_Bot) ([source](https://github.com/arashnm80/best-instagram-downloader)) by [Arashnm80](https://github.com/arashnm80). Free and open source telegram bot to download posts and reels from Instagram. * [Personal bot for ChatGPT & Bard](https://github.com/Simatwa/pyTelegramBotAPI.git) by [Simatwa](https://github.com/Simatwa/telegram-chatbots). Chat with ChatGPT & Bard on the go. +* [4K YouTube Downloader](https://github.com/hansanaD/TelegramYTDLBot/) - Youtube Downloader with upto 4K resolution support. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From 0570bf1166b622d7e78fc2c6f5cc8a36d253a3e1 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 28 Feb 2024 11:16:14 +0300 Subject: [PATCH 170/480] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ad8d01fae..6bda55484 100644 --- a/README.md +++ b/README.md @@ -888,7 +888,6 @@ Here are some examples of template: * [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles! * [QR-Code For You Bot](https://t.me/qrcode_for_you_bot) ([source](https://github.com/arashnm80/qrcode-for-you-bot)) by [Arashnm80](https://github.com/arashnm80). Telegram qrcode generator bot created with pyhton and telebot. * [Best Instagram Downloader Bot](https://t.me/Best_Instagram_Downloader_Bot) ([source](https://github.com/arashnm80/best-instagram-downloader)) by [Arashnm80](https://github.com/arashnm80). Free and open source telegram bot to download posts and reels from Instagram. -* [Personal bot for ChatGPT & Bard](https://github.com/Simatwa/pyTelegramBotAPI.git) by [Simatwa](https://github.com/Simatwa/telegram-chatbots). Chat with ChatGPT & Bard on the go. * [4K YouTube Downloader](https://github.com/hansanaD/TelegramYTDLBot/) - Youtube Downloader with upto 4K resolution support. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From 6391348a2074f5e0503e2d636af83a4fd83423a6 Mon Sep 17 00:00:00 2001 From: Ivan Popravka Date: Sun, 10 Mar 2024 21:47:50 +0300 Subject: [PATCH 171/480] Add new bot to the list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6bda55484..aeb4f1686 100644 --- a/README.md +++ b/README.md @@ -889,5 +889,6 @@ Here are some examples of template: * [QR-Code For You Bot](https://t.me/qrcode_for_you_bot) ([source](https://github.com/arashnm80/qrcode-for-you-bot)) by [Arashnm80](https://github.com/arashnm80). Telegram qrcode generator bot created with pyhton and telebot. * [Best Instagram Downloader Bot](https://t.me/Best_Instagram_Downloader_Bot) ([source](https://github.com/arashnm80/best-instagram-downloader)) by [Arashnm80](https://github.com/arashnm80). Free and open source telegram bot to download posts and reels from Instagram. * [4K YouTube Downloader](https://github.com/hansanaD/TelegramYTDLBot/) - Youtube Downloader with upto 4K resolution support. +* [DrinkGenius-Bot](https://t.me/cocktail_recommendation_bot) ([source](https://github.com/Povladarchik/DrinkGenius-Bot)) by [Povladarchik](https://github.com/Povladarchik). Your personal assistant in the world of cocktails. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From 6bb3968376c93666f7b57f206a94135e9a9cde8b Mon Sep 17 00:00:00 2001 From: Suren Khorenyan Date: Mon, 18 Mar 2024 15:04:32 +0300 Subject: [PATCH 172/480] Fix TextFilter error: if no message text and no caption -> return False --- telebot/custom_filters.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index e924f134c..d4d4ffeca 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -149,6 +149,8 @@ def check(self, obj: Union[types.Message, types.CallbackQuery, types.InlineQuery text = obj.question elif isinstance(obj, types.Message): text = obj.text or obj.caption + if text is None: + return False elif isinstance(obj, types.CallbackQuery): text = obj.data elif isinstance(obj, types.InlineQuery): From 3a50a2140097df81d8ebc42fca9e39b137407cec Mon Sep 17 00:00:00 2001 From: Jacopo Tediosi Date: Thu, 28 Mar 2024 15:49:38 +0100 Subject: [PATCH 173/480] Retry engine 2 backoff fixes Retry engine 2 behaved differently than retry engine 1. In particular, POST requests were not retried, because they were not included in the `allowed_methods` parameter of the urllib3 Retry strategy. Furthermore, requests were retried without delay, ignoring the `RETRY_TIMEOUT` setting, because also the `backoff_` parameters were not implemented in the the urllib3 Retry strategy. This commit aims to fix these problems, implementing the `allowed_methods`, `backoff_factor` and `backoff_max` parameters in the urllib3 Retry strategy. It is important to note that `urllib3.util.Retry` does not allow you to directly set a fixed backoff delay, so I set `backoff_factor=RETRY_TIMEOUT` and `backoff_max=RETRY_TIMEOUT`. In this way, already on the second request, the backoff delay exceeds the `backoff_max` and remains so. For more information, see the [urllib3.util.Retry](https://urllib3.readthedocs.io/en/stable/reference/urllib3.util.html) documentation. --- telebot/apihelper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 599874820..3b1b2a29c 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -147,6 +147,9 @@ def _make_request(token, method_name, method='get', params=None, files=None): # noinspection PyUnresolvedReferences retry_strategy = requests.packages.urllib3.util.retry.Retry( total=MAX_RETRIES, + allowed_methods=None, + backoff_factor=RETRY_TIMEOUT, + backoff_max=RETRY_TIMEOUT ) adapter = HTTPAdapter(max_retries=retry_strategy) for prefix in ('http://', 'https://'): From 12e9673adcaa308fc125937e2a5672cbb3243795 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 31 Mar 2024 23:46:54 +0500 Subject: [PATCH 174/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aeb4f1686..20b062e70 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.1! +##

Supported Bot API version: 7.2!

Official documentation

Official ru documentation

From dcf856652b8b887972b25a9e5f687b8a47d28171 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 00:00:58 +0500 Subject: [PATCH 175/480] Added the class BusinessConnection and updates about the connection or disconnection of the bot to a business account, represented by the field business_connection in the class Update. --- telebot/types.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 222048cfc..41043fdf7 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -178,6 +178,9 @@ class Update(JsonDeserializable): :param removed_chat_boost: Optional. A chat boost was removed. The bot must be an administrator in the chat to receive these updates. :type removed_chat_boost: :class:`telebot.types.RemovedChatBoost` + :param business_connection: Optional. The bot was connected to or disconnected from a business account, or a user edited an existing connection with the bot + :type business_connection: :class:`telebot.types.BusinessConnection` + :return: Instance of the class :rtype: :class:`telebot.types.Update` @@ -205,13 +208,16 @@ def de_json(cls, json_string): message_reaction_count = MessageReactionCountUpdated.de_json(obj.get('message_reaction_count')) removed_chat_boost = ChatBoostRemoved.de_json(obj.get('removed_chat_boost')) chat_boost = ChatBoostUpdated.de_json(obj.get('chat_boost')) + business_connection = BusinessConnection.de_json(obj.get('business_connection')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, + business_connection) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost): + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, + business_connection, **kwargs): self.update_id = update_id self.message = message self.edited_message = edited_message @@ -231,6 +237,8 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.message_reaction_count = message_reaction_count self.removed_chat_boost = removed_chat_boost self.chat_boost = chat_boost + self.business_connection = business_connection + class ChatMemberUpdated(JsonDeserializable): @@ -9308,3 +9316,50 @@ def de_json(cls, json_string): def __init__(self, boost_count, **kwargs): self.boost_count: int = boost_count + + + +class BusinessConnection(JsonDeserializable): + """ + This object describes the connection of the bot with a business account. + + Telegram documentation: https://core.telegram.org/bots/api#businessconnection + + :param id: Unique identifier of the business connection + :type id: :obj:`str` + + :param user: Business account user that created the business connection + :type user: :class:`User` + + :param user_chat_id: Identifier of a private chat with the user who created the business connection + :type user_chat_id: :obj:`int` + + :param date: Date the connection was established in Unix time + :type date: :obj:`int` + + :param can_reply: True, if the bot can act on behalf of the business account in chats that were active in the last 24 hours + :type can_reply: :obj:`bool` + + :param is_enabled: True, if the connection is active + :type is_enabled: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`BusinessConnection` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['user'] = User.de_json(obj['user']) + return cls(**obj) + + def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, **kwargs): + self.id: str = id + self.user: User = user + self.user_chat_id: int = user_chat_id + self.date: int = date + self.can_reply: bool = can_reply + self.is_enabled: bool = is_enabled + + From f223cfb9b8f6779c10565c043f1f7fabaae2b908 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 00:27:41 +0500 Subject: [PATCH 176/480] Added 4 handlers; needs testing --- telebot/__init__.py | 397 +++++++++++++++++++++++++++++++++++++++ telebot/async_telebot.py | 394 ++++++++++++++++++++++++++++++++++++++ telebot/types.py | 53 +++++- 3 files changed, 842 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 39a9c25aa..e3eec483f 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -231,6 +231,11 @@ def __init__( self.chat_join_request_handlers = [] self.chat_boost_handlers = [] self.removed_chat_boost_handlers = [] + self.business_connection_handlers = [] + self.business_message_handlers = [] + self.edited_business_message_handlers = [] + self.deleted_business_messages_handlers = [] + self.custom_filters = {} self.state_handlers = [] @@ -694,6 +699,10 @@ def process_new_updates(self, updates: List[types.Update]): new_chat_join_request = None new_chat_boosts = None new_removed_chat_boosts = None + new_business_connections = None + new_business_messages = None + new_edited_business_messages = None + new_deleted_business_messages = None for update in updates: if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares: @@ -763,6 +772,19 @@ def process_new_updates(self, updates: List[types.Update]): if update.removed_chat_boost: if new_removed_chat_boosts is None: new_removed_chat_boosts = [] new_removed_chat_boosts.append(update.removed_chat_boost) + if update.business_connection: + if new_business_connections is None: new_business_connections = [] + new_business_connections.append(update.business_connection) + if update.business_message: + if new_business_messages is None: new_business_messages = [] + new_business_messages.append(update.business_message) + if update.edited_business_message: + if new_edited_business_messages is None: new_edited_business_messages = [] + new_edited_business_messages.append(update.edited_business_message) + if update.deleted_business_messages: + if new_deleted_business_messages is None: new_deleted_business_messages = [] + new_deleted_business_messages.append(update.deleted_business_messages) + if new_messages: self.process_new_messages(new_messages) @@ -800,6 +822,14 @@ def process_new_updates(self, updates: List[types.Update]): self.process_new_chat_boost(new_chat_boosts) if new_removed_chat_boosts: self.process_new_removed_chat_boost(new_removed_chat_boosts) + if new_business_connections: + self.process_new_business_connection(new_business_connections) + if new_business_messages: + self.process_new_business_message(new_business_messages) + if new_edited_business_messages: + self.process_new_edited_business_message(new_edited_business_messages) + if new_deleted_business_messages: + self.process_new_deleted_business_messages(new_deleted_business_messages) def process_new_messages(self, new_messages): """ @@ -912,6 +942,32 @@ def process_new_removed_chat_boost(self, new_removed_chat_boosts): """ self._notify_command_handlers(self.removed_chat_boost_handlers, new_removed_chat_boosts, 'removed_chat_boost') + def process_new_business_connection(self, new_business_connections): + """ + :meta private: + """ + self._notify_command_handlers(self.business_connection_handlers, new_business_connections, 'business_connection') + + def process_new_business_message(self, new_business_messages): + """ + :meta private: + """ + self._notify_command_handlers(self.business_message_handlers, new_business_messages, 'business_message') + + def process_new_edited_business_message(self, new_edited_business_messages): + """ + :meta private: + """ + self._notify_command_handlers(self.edited_business_message_handlers, new_edited_business_messages, 'edited_business_message') + + def process_new_deleted_business_messages(self, new_deleted_business_messages): + """ + :meta private: + """ + self._notify_command_handlers(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages') + + + def process_middlewares(self, update): """ @@ -7761,6 +7817,347 @@ def register_removed_chat_boost_handler( handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_removed_chat_boost_handler(handler_dict) + def business_connection_handler(self, func=None, **kwargs): + """ + Handles new incoming business connection state. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_business_connection_handler(handler_dict) + return handler + + return decorator + + def add_business_connection_handler(self, handler_dict): + """ + Adds a business_connection handler. + Note that you should use register_business_connection_handler to add business_connection_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.business_connection_handlers.append(handler_dict) + + def register_business_connection_handler( + self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + """ + Registers business connection handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_business_connection_handler(handler_dict) + + def business_message_handler( + self, + commands: Optional[List[str]]=None, + regexp: Optional[str]=None, + func: Optional[Callable]=None, + content_types: Optional[List[str]]=None, + **kwargs): + """ + Handles New incoming message of any kind(for business accounts, see bot api 7.2 for more) - text, photo, sticker, etc. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + All message handlers are tested in the order they were added. + + Example: + + .. code-block:: python3 + :caption: Usage of business_message_handler + + bot = TeleBot('TOKEN') + + # Handles all messages which text matches regexp. + @bot.business_message_handler(regexp='someregexp') + def command_help(message): + bot.send_message(message.chat.id, 'Did someone call for help?') + + # Handle all sent documents of type 'text/plain'. + @bot.business_message_handler(func=lambda message: message.document.mime_type == 'text/plain', + content_types=['document']) + def command_handle_document(message): + bot.send_message(message.chat.id, 'Document received, sir!') + + # Handle all other messages. + @bot.business_message_handler(func=lambda message: True, content_types=['audio', 'photo', 'voice', 'video', 'document', + 'text', 'location', 'contact', 'sticker']) + def default_command(message): + bot.send_message(message.chat.id, "This is the default command handler.") + + :param commands: Optional list of strings (commands to handle). + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Optional regular expression. + :type regexp: :obj:`str` + + :param func: Optional lambda function. The lambda receives the message to test as the first parameter. + It must return True if the command should handle the message. + :type func: :obj:`lambda` + + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: decorated function + """ + if content_types is None: + content_types = ["text"] + + method_name = "business_message_handler" + + if commands is not None: + self.check_commands_input(commands, method_name) + if isinstance(commands, str): + commands = [commands] + + if regexp is not None: + self.check_regexp_input(regexp, method_name) + + if isinstance(content_types, str): + logger.warning("business_message_handler: 'content_types' filter should be List of strings (content types), not string.") + content_types = [content_types] + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, + content_types=content_types, + commands=commands, + regexp=regexp, + func=func, + **kwargs) + self.add_message_handler(handler_dict) + return handler + + return decorator + + def add_business_message_handler(self, handler_dict): + """ + Adds a business_message handler. + Note that you should use register_business_message_handler to add business_message_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.business_message_handlers.append(handler_dict) + + def register_business_message_handler(self, + callback: Callable, + commands: Optional[List[str]]=None, + regexp: Optional[str]=None, + func: Optional[Callable]=None, + content_types: Optional[List[str]]=None, + **kwargs): + """ + Registers business connection handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, **kwargs) + self.add_business_message_handler(handler_dict) + + + + + def edited_business_message_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs): + """ + Handles new version of a message(business accounts) that is known to the bot and was edited. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + + :param commands: Optional list of strings (commands to handle). + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Optional regular expression. + :type regexp: :obj:`str` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + if content_types is None: + content_types = ["text"] + + method_name = "edited_business_message_handler" + + if commands is not None: + self.check_commands_input(commands, method_name) + if isinstance(commands, str): + commands = [commands] + + if regexp is not None: + self.check_regexp_input(regexp, method_name) + + if isinstance(content_types, str): + logger.warning("edited_business_message_handler: 'content_types' filter should be List of strings (content types), not string.") + content_types = [content_types] + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, + content_types=content_types, + commands=commands, + regexp=regexp, + func=func, + **kwargs) + self.add_edited_message_handler(handler_dict) + return handler + + return decorator + + + def add_edited_business_message_handler(self, handler_dict): + """ + Adds the edit message handler + Note that you should use register_edited_business_message_handler to add edited_business_message_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.edited_message_handlers.append(handler_dict) + + + def register_edited_business_message_handler(self, callback: Callable, content_types: Optional[List[str]]=None, + commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, + pass_bot: Optional[bool]=False, **kwargs): + """ + Registers edited message handler for business accounts. + + :param callback: function to be called + :type callback: :obj:`function` + + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` + + :param commands: list of commands + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Regular expression + :type regexp: :obj:`str` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + method_name = "edited_business_message_handler" + + if commands is not None: + self.check_commands_input(commands, method_name) + if isinstance(commands, str): + commands = [commands] + + if regexp is not None: + self.check_regexp_input(regexp, method_name) + + if isinstance(content_types, str): + logger.warning("edited_business_message_handler: 'content_types' filter should be List of strings (content types), not string.") + content_types = [content_types] + + handler_dict = self._build_handler_dict(callback, + content_types=content_types, + commands=commands, + regexp=regexp, + func=func, + pass_bot=pass_bot, + **kwargs) + self.add_edited_business_message_handler(handler_dict) + + + def deleted_business_messages_handler(self, func=None, **kwargs): + """ + Handles new incoming deleted messages state. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + + self.add_deleted_message_handler(handler_dict) + return handler + + return decorator + + def add_deleted_business_messages_handler(self, handler_dict): + """ + Adds a deleted_business_messages handler. + Note that you should use register_deleted_business_messages_handler to add deleted_business_messages_handler to the bot. + + :meta private: + """ + self.deleted_message_handlers.append(handler_dict) + + def register_deleted_business_messages_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers deleted business messages handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_deleted_business_messages_handler(handler_dict) + + + + def add_custom_filter(self, custom_filter: Union[SimpleCustomFilter, AdvancedCustomFilter]): """ diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index fece7a2e7..88b29de3a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -173,6 +173,11 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.chat_join_request_handlers = [] self.removed_chat_boost_handlers = [] self.chat_boost_handlers = [] + self.business_connection_handlers = [] + self.business_message_handlers = [] + self.edited_business_message_handlers = [] + self.deleted_business_messages_handlers = [] + self.custom_filters = {} self.state_handlers = [] self.middlewares = [] @@ -594,6 +599,12 @@ async def process_new_updates(self, updates: List[types.Update]): chat_join_request = None removed_chat_boost_handlers = None chat_boost_handlers = None + new_business_connections = None + new_business_messages = None + new_edited_business_messages = None + new_deleted_business_messages = None + + for update in updates: logger.debug('Processing updates: {0}'.format(update)) if update.message: @@ -650,6 +661,18 @@ async def process_new_updates(self, updates: List[types.Update]): if update.removed_chat_boost: if removed_chat_boost_handlers is None: removed_chat_boost_handlers = [] removed_chat_boost_handlers.append(update.removed_chat_boost) + if update.business_connection: + if new_business_connections is None: new_business_connections = [] + new_business_connections.append(update.business_connection) + if update.business_message: + if new_business_messages is None: new_business_messages = [] + new_business_messages.append(update.business_message) + if update.edited_business_message: + if new_edited_business_messages is None: new_edited_business_messages = [] + new_edited_business_messages.append(update.edited_business_message) + if update.deleted_business_messages: + if new_deleted_business_messages is None: new_deleted_business_messages = [] + new_deleted_business_messages.append(update.deleted_business_messages) if new_messages: @@ -686,6 +709,14 @@ async def process_new_updates(self, updates: List[types.Update]): await self.process_new_message_reaction_count(new_message_reaction_count_handlers) if chat_boost_handlers: await self.process_new_chat_boost(chat_boost_handlers) + if new_business_connections: + await self.process_new_business_connection(new_business_connections) + if new_business_messages: + await self.process_new_business_message(new_business_messages) + if new_edited_business_messages: + await self.process_new_edited_business_message(new_edited_business_messages) + if new_deleted_business_messages: + await self.process_new_deleted_business_messages(new_deleted_business_messages) async def process_new_messages(self, new_messages): """ @@ -796,6 +827,30 @@ async def process_new_removed_chat_boost(self, removed_chat_boost): """ await self._process_updates(self.removed_chat_boost_handlers, removed_chat_boost, 'removed_chat_boost') + async def process_new_business_connection(self, new_business_connections): + """ + :meta private: + """ + await self._process_updates(self.business_connection_handlers, new_business_connections, 'business_connection') + + async def process_new_business_message(self, new_business_messages): + """ + :meta private: + """ + await self._process_updates(self.business_message_handlers, new_business_messages, 'business_message') + + async def process_new_edited_business_message(self, new_edited_business_messages): + """ + :meta private: + """ + await self._process_updates(self.edited_business_message_handlers, new_edited_business_messages, 'edited_business_message') + + async def process_new_deleted_business_messages(self, new_deleted_business_messages): + """ + :meta private: + """ + await self._process_updates(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages') + async def _get_middlewares(self, update_type): """ :meta private: @@ -2125,6 +2180,345 @@ def register_removed_chat_boost_handler(self, callback: Callable, func: Optional handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_removed_chat_boost_handler(handler_dict) + + def business_connection_handler(self, func=None, **kwargs): + """ + Handles new incoming business connection state. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_business_connection_handler(handler_dict) + return handler + + return decorator + + def add_business_connection_handler(self, handler_dict): + """ + Adds a business_connection handler. + Note that you should use register_business_connection_handler to add business_connection_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.business_connection_handlers.append(handler_dict) + + def register_business_connection_handler( + self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): + """ + Registers business connection handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_business_connection_handler(handler_dict) + + def business_message_handler( + self, + commands: Optional[List[str]]=None, + regexp: Optional[str]=None, + func: Optional[Callable]=None, + content_types: Optional[List[str]]=None, + **kwargs): + """ + Handles New incoming message of any kind(for business accounts, see bot api 7.2 for more) - text, photo, sticker, etc. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + All message handlers are tested in the order they were added. + + Example: + + .. code-block:: python3 + :caption: Usage of business_message_handler + + bot = TeleBot('TOKEN') + + # Handles all messages which text matches regexp. + @bot.business_message_handler(regexp='someregexp') + def command_help(message): + bot.send_message(message.chat.id, 'Did someone call for help?') + + # Handle all sent documents of type 'text/plain'. + @bot.business_message_handler(func=lambda message: message.document.mime_type == 'text/plain', + content_types=['document']) + def command_handle_document(message): + bot.send_message(message.chat.id, 'Document received, sir!') + + # Handle all other messages. + @bot.business_message_handler(func=lambda message: True, content_types=['audio', 'photo', 'voice', 'video', 'document', + 'text', 'location', 'contact', 'sticker']) + def default_command(message): + bot.send_message(message.chat.id, "This is the default command handler.") + + :param commands: Optional list of strings (commands to handle). + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Optional regular expression. + :type regexp: :obj:`str` + + :param func: Optional lambda function. The lambda receives the message to test as the first parameter. + It must return True if the command should handle the message. + :type func: :obj:`lambda` + + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: decorated function + """ + if content_types is None: + content_types = ["text"] + + method_name = "business_message_handler" + + if commands is not None: + self.check_commands_input(commands, method_name) + if isinstance(commands, str): + commands = [commands] + + if regexp is not None: + self.check_regexp_input(regexp, method_name) + + if isinstance(content_types, str): + logger.warning("business_message_handler: 'content_types' filter should be List of strings (content types), not string.") + content_types = [content_types] + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, + content_types=content_types, + commands=commands, + regexp=regexp, + func=func, + **kwargs) + self.add_message_handler(handler_dict) + return handler + + return decorator + + def add_business_message_handler(self, handler_dict): + """ + Adds a business_message handler. + Note that you should use register_business_message_handler to add business_message_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.business_message_handlers.append(handler_dict) + + def register_business_message_handler(self, + callback: Callable, + commands: Optional[List[str]]=None, + regexp: Optional[str]=None, + func: Optional[Callable]=None, + content_types: Optional[List[str]]=None, + **kwargs): + """ + Registers business connection handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, **kwargs) + self.add_business_message_handler(handler_dict) + + + + + def edited_business_message_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs): + """ + Handles new version of a message(business accounts) that is known to the bot and was edited. + As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. + + :param commands: Optional list of strings (commands to handle). + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Optional regular expression. + :type regexp: :obj:`str` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + if content_types is None: + content_types = ["text"] + + method_name = "edited_business_message_handler" + + if commands is not None: + self.check_commands_input(commands, method_name) + if isinstance(commands, str): + commands = [commands] + + if regexp is not None: + self.check_regexp_input(regexp, method_name) + + if isinstance(content_types, str): + logger.warning("edited_business_message_handler: 'content_types' filter should be List of strings (content types), not string.") + content_types = [content_types] + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, + content_types=content_types, + commands=commands, + regexp=regexp, + func=func, + **kwargs) + self.add_edited_message_handler(handler_dict) + return handler + + return decorator + + + def add_edited_business_message_handler(self, handler_dict): + """ + Adds the edit message handler + Note that you should use register_edited_business_message_handler to add edited_business_message_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.edited_message_handlers.append(handler_dict) + + + def register_edited_business_message_handler(self, callback: Callable, content_types: Optional[List[str]]=None, + commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, + pass_bot: Optional[bool]=False, **kwargs): + """ + Registers edited message handler for business accounts. + + :param callback: function to be called + :type callback: :obj:`function` + + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` + + :param commands: list of commands + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Regular expression + :type regexp: :obj:`str` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + method_name = "edited_business_message_handler" + + if commands is not None: + self.check_commands_input(commands, method_name) + if isinstance(commands, str): + commands = [commands] + + if regexp is not None: + self.check_regexp_input(regexp, method_name) + + if isinstance(content_types, str): + logger.warning("edited_business_message_handler: 'content_types' filter should be List of strings (content types), not string.") + content_types = [content_types] + + handler_dict = self._build_handler_dict(callback, + content_types=content_types, + commands=commands, + regexp=regexp, + func=func, + pass_bot=pass_bot, + **kwargs) + self.add_edited_business_message_handler(handler_dict) + + + def deleted_business_messages_handler(self, func=None, **kwargs): + """ + Handles new incoming deleted messages state. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + :return: None + + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + + self.add_deleted_message_handler(handler_dict) + return handler + + return decorator + + def add_deleted_business_messages_handler(self, handler_dict): + """ + Adds a deleted_business_messages handler. + Note that you should use register_deleted_business_messages_handler to add deleted_business_messages_handler to the bot. + + :meta private: + """ + self.deleted_message_handlers.append(handler_dict) + + def register_deleted_business_messages_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers deleted business messages handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_deleted_business_messages_handler(handler_dict) + @staticmethod def _build_handler_dict(handler, pass_bot=False, **filters): """ diff --git a/telebot/types.py b/telebot/types.py index 41043fdf7..fbb857ae0 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -181,6 +181,15 @@ class Update(JsonDeserializable): :param business_connection: Optional. The bot was connected to or disconnected from a business account, or a user edited an existing connection with the bot :type business_connection: :class:`telebot.types.BusinessConnection` + :param business_message: Optional. New non-service message from a connected business account + :type business_message: :class:`telebot.types.Message` + + :param edited_business_message: Optional. New version of a non-service message from a connected business account that is known to the bot and was edited + :type edited_business_message: :class:`telebot.types.Message` + + :param deleted_business_messages: Optional. Service message: the chat connected to the business account was deleted + :type deleted_business_messages: :class:`telebot.types.Message` + :return: Instance of the class :rtype: :class:`telebot.types.Update` @@ -209,15 +218,19 @@ def de_json(cls, json_string): removed_chat_boost = ChatBoostRemoved.de_json(obj.get('removed_chat_boost')) chat_boost = ChatBoostUpdated.de_json(obj.get('chat_boost')) business_connection = BusinessConnection.de_json(obj.get('business_connection')) + business_message = Message.de_json(obj.get('business_message')) + edited_business_message = Message.de_json(obj.get('edited_business_message')) + deleted_business_messages = Message.de_json(obj.get('deleted_business_messages')) + return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, - business_connection) + business_connection, business_message, edited_business_message, deleted_business_messages, **obj) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, - business_connection, **kwargs): + business_connection, business_message, edited_business_message, deleted_business_messages, **kwargs): self.update_id = update_id self.message = message self.edited_message = edited_message @@ -238,6 +251,9 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.removed_chat_boost = removed_chat_boost self.chat_boost = chat_boost self.business_connection = business_connection + self.business_message = business_message + self.edited_business_message = edited_business_message + self.deleted_business_messages = deleted_business_messages @@ -9363,3 +9379,36 @@ def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, **kwargs self.is_enabled: bool = is_enabled + +class BusinessMessagesDeleted(JsonDeserializable): + """ + This object is received when messages are deleted from a connected business account. + + Telegram documentation: https://core.telegram.org/bots/api#businessmessagesdeleted + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param chat: Information about a chat in the business account. The bot may not have access to the chat or the corresponding user. + :type chat: :class:`Chat` + + :param message_ids: A JSON-serialized list of identifiers of deleted messages in the chat of the business account + :type message_ids: :obj:`list` of :obj:`int` + + :return: Instance of the class + :rtype: :class:`BusinessMessagesDeleted` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) + return cls(**obj) + + + def __init__(self, business_connection_id, chat, message_ids, **kwargs): + self.business_connection_id: str = business_connection_id + self.chat: Chat = chat + self.message_ids: List[int] = message_ids + \ No newline at end of file From 2f61473d233560d1024b4d4e968a9d023a4cb84a Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 00:36:21 +0500 Subject: [PATCH 177/480] added getbusinessconnection --- telebot/__init__.py | 21 ++++++++++++++++++++- telebot/apihelper.py | 4 ++++ telebot/async_telebot.py | 20 ++++++++++++++++++++ telebot/asyncio_helper.py | 4 ++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index e3eec483f..ced007f93 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4280,6 +4280,25 @@ def get_my_default_administrator_rights(self, for_channels: Optional[bool]=None) apihelper.get_my_default_administrator_rights(self.token, for_channels=for_channels) ) + + def get_business_connection(self, business_connection_id: str) -> types.BusinessConnection: + """ + Use this method to get information about the connection of the bot with a business account. + Returns a BusinessConnection object on success. + + Telegram documentation: https://core.telegram.org/bots/api#getbusinessconnection + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :return: Returns a BusinessConnection object on success. + :rtype: :class:`telebot.types.BusinessConnection` + """ + + return types.BusinessConnection.de_json( + apihelper.get_business_connection(self.token, business_connection_id) + ) + def set_my_commands(self, commands: List[types.BotCommand], scope: Optional[types.BotCommandScope]=None, @@ -8155,7 +8174,7 @@ def register_deleted_business_messages_handler(self, callback: Callable, func: O handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_deleted_business_messages_handler(handler_dict) - + diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 3b1b2a29c..eb7a30219 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1247,6 +1247,10 @@ def set_my_commands(token, commands, scope=None, language_code=None): payload['language_code'] = language_code return _make_request(token, method_url, params=payload, method='post') +def get_business_connection(token, business_connection_id): + method_url = 'getBusinessConnection' + payload = {'business_connection_id': business_connection_id} + return _make_request(token, method_url, params=payload , method='post') def delete_my_commands(token, scope=None, language_code=None): method_url = r'deleteMyCommands' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 88b29de3a..37dc712bc 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5647,6 +5647,26 @@ async def get_my_default_administrator_rights(self, for_channels: bool=None) -> """ return types.ChatAdministratorRights.de_json(await asyncio_helper.get_my_default_administrator_rights(self.token, for_channels)) + + async def get_business_connection(self, business_connection_id: str) -> types.BusinessConnection: + """ + Use this method to get information about the connection of the bot with a business account. + Returns a BusinessConnection object on success. + + Telegram documentation: https://core.telegram.org/bots/api#getbusinessconnection + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :return: Returns a BusinessConnection object on success. + :rtype: :class:`telebot.types.BusinessConnection` + """ + result = await asyncio_helper.get_business_connection(self.token, business_connection_id) + + return types.BusinessConnection.de_json( + result + ) + async def set_my_commands(self, commands: List[types.BotCommand], scope: Optional[types.BotCommandScope]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 2b6bc2ce3..ceafe637f 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1234,6 +1234,10 @@ async def set_my_commands(token, commands, scope=None, language_code=None): payload['language_code'] = language_code return await _process_request(token, method_url, params=payload, method='post') +async def get_business_connection(token, business_connection_id): + method_url = 'getBusinessConnection' + payload = {'business_connection_id': business_connection_id} + return await _process_request(token, method_url, params=payload , method='post') async def delete_my_commands(token, scope=None, language_code=None): method_url = r'deleteMyCommands' From 91143eb04c4125e9bceee32774d8a90c305e412a Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:09:39 +0500 Subject: [PATCH 178/480] added business connection ids --- telebot/__init__.py | 129 +++++++++++++++++++++++++++--------- telebot/apihelper.py | 64 +++++++++++++----- telebot/async_telebot.py | 134 ++++++++++++++++++++++++++++---------- telebot/asyncio_helper.py | 61 ++++++++++++----- telebot/types.py | 2 +- 5 files changed, 292 insertions(+), 98 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index ced007f93..291b77ead 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1630,7 +1630,8 @@ def send_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - link_preview_options : Optional[types.LinkPreviewOptions]=None) -> types.Message: + link_preview_options : Optional[types.LinkPreviewOptions]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send text messages. @@ -1683,6 +1684,9 @@ def send_message( :param link_preview_options: Link preview options. :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1730,7 +1734,7 @@ def send_message( self.token, chat_id, text, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, entities=entities, protect_content=protect_content, message_thread_id=message_thread_id, - reply_parameters=reply_parameters, link_preview_options=link_preview_options)) + reply_parameters=reply_parameters, link_preview_options=link_preview_options, business_connection_id=business_connection_id)) def forward_message( @@ -2017,7 +2021,8 @@ def send_dice( allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -2056,6 +2061,9 @@ def send_dice( :param reply_parameters: Additional parameters for replies to messages :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2084,7 +2092,7 @@ def send_dice( apihelper.send_dice( self.token, chat_id, emoji=emoji, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) ) @@ -2100,7 +2108,8 @@ def send_photo( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2151,6 +2160,9 @@ def send_photo( :param reply_parameters: Additional parameters for replies to messages :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2182,7 +2194,7 @@ def send_photo( self.token, chat_id, photo, caption=caption, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters) + message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) ) @@ -2201,7 +2213,8 @@ def send_audio( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -2271,6 +2284,9 @@ def send_audio( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2305,7 +2321,7 @@ def send_audio( self.token, chat_id, audio, caption=caption, duration=duration, performer=performer, title=title, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -2321,7 +2337,8 @@ def send_voice( allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). @@ -2374,6 +2391,9 @@ def send_voice( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -2403,7 +2423,7 @@ def send_voice( self.token, chat_id, voice, caption=caption, duration=duration, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -2423,7 +2443,8 @@ def send_document( data: Optional[Union[Any, str]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send general files. @@ -2486,6 +2507,9 @@ def send_document( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2525,7 +2549,7 @@ def send_document( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption=caption, thumbnail=thumbnail, caption_entities=caption_entities, disable_content_type_detection=disable_content_type_detection, visible_file_name=visible_file_name, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -2541,7 +2565,8 @@ def send_sticker( data: Union[Any, str]=None, message_thread_id: Optional[int]=None, emoji: Optional[str]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -2587,6 +2612,9 @@ def send_sticker( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2620,7 +2648,7 @@ def send_sticker( self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, - reply_parameters=reply_parameters) + reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -2644,7 +2672,8 @@ def send_video( message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2715,6 +2744,9 @@ def send_video( :param reply_parameters: Reply parameters :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2755,7 +2787,7 @@ def send_video( supports_streaming=supports_streaming, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, - reply_parameters=reply_parameters) + reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -2777,7 +2809,8 @@ def send_animation( message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -2847,6 +2880,9 @@ def send_animation( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2882,7 +2918,7 @@ def send_animation( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - has_spoiler=has_spoiler) + has_spoiler=has_spoiler, business_connection_id=business_connection_id) ) @@ -2899,7 +2935,8 @@ def send_video_note( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -2954,6 +2991,9 @@ def send_video_note( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2986,7 +3026,7 @@ def send_video_note( apihelper.send_video_note( self.token, chat_id, data, duration=duration, length=length, reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -3001,7 +3041,8 @@ def send_media_group( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -3035,6 +3076,9 @@ def send_media_group( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -3061,7 +3105,8 @@ def send_media_group( result = apihelper.send_media_group( self.token, chat_id, media, disable_notification=disable_notification, timeout=timeout, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, + business_connection_id=business_connection_id) return [types.Message.de_json(msg) for msg in result] @@ -3079,7 +3124,8 @@ def send_location( allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -3132,6 +3178,9 @@ def send_location( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3161,7 +3210,7 @@ def send_location( self.token, chat_id, latitude, longitude, live_period=live_period, reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, proximity_alert_radius=proximity_alert_radius, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -3277,7 +3326,8 @@ def send_venue( google_place_type: Optional[str]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -3337,6 +3387,9 @@ def send_venue( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3366,7 +3419,7 @@ def send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id=foursquare_id, foursquare_type=foursquare_type, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, google_place_id=google_place_id, google_place_type=google_place_type, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -3380,7 +3433,8 @@ def send_contact( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -3427,6 +3481,9 @@ def send_contact( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3455,7 +3512,7 @@ def send_contact( apihelper.send_contact( self.token, chat_id, phone_number, first_name, last_name=last_name, vcard=vcard, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -4618,7 +4675,8 @@ def send_game( allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Used to send the game. @@ -4654,6 +4712,9 @@ def send_game( :param reply_parameters: Reply parameters :type reply_parameters: :obj:`ReplyParameters` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -4685,7 +4746,7 @@ def send_game( apihelper.send_game( self.token, chat_id, game_short_name, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) @@ -5059,7 +5120,8 @@ def send_poll( explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -5133,6 +5195,9 @@ def send_poll( :param reply_parameters: reply parameters. :type reply_parameters: :obj:`ReplyParameters` + :param business_connection_id: Identifier of the business connection to use for the poll + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5174,7 +5239,7 @@ def send_poll( close_date=close_date, is_closed=is_closed, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, explanation_entities=explanation_entities, protect_content=protect_content, message_thread_id=message_thread_id, - reply_parameters=reply_parameters) + reply_parameters=reply_parameters, business_connection_id=business_connection_id) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index eb7a30219..93632ac05 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -243,7 +243,8 @@ def send_message( reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, - message_thread_id=None, reply_parameters=None, link_preview_options=None): + message_thread_id=None, reply_parameters=None, link_preview_options=None, + business_connection_id=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -264,6 +265,8 @@ def send_message( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') @@ -441,7 +444,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m def send_dice( token, chat_id, emoji=None, disable_notification=None, - reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None): + reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, + business_connection_id=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -458,6 +462,8 @@ def send_dice( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) @@ -466,7 +472,7 @@ def send_photo( caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -496,13 +502,15 @@ def send_photo( payload['has_spoiler'] = has_spoiler if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_media_group( token, chat_id, media, disable_notification=None, - timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None): + timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendMediaGroup' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -516,6 +524,8 @@ def send_media_group( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request( token, method_url, params=payload, method='post' if files else 'get', @@ -528,7 +538,7 @@ def send_location( reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, - message_thread_id=None, reply_parameters=None): + message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -551,6 +561,8 @@ def send_location( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) @@ -601,7 +613,7 @@ def send_venue( token, chat_id, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, - google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None): + google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -624,13 +636,15 @@ def send_venue( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None, reply_parameters=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -649,6 +663,8 @@ def send_contact( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) @@ -666,7 +682,7 @@ def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=Non def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -710,6 +726,9 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['has_spoiler'] = has_spoiler if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id + return _make_request(token, method_url, params=payload, files=files, method='post') @@ -717,7 +736,7 @@ def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, - has_spoiler=None): + has_spoiler=None, business_connection_id=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -759,12 +778,14 @@ def send_animation( payload['has_spoiler'] = has_spoiler if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - protect_content=None, message_thread_id=None, reply_parameters=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -792,12 +813,14 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None, reply_parameters=None): + message_thread_id=None, reply_parameters=None,business_connection_id=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -831,12 +854,14 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, - caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None): + caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -876,13 +901,15 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, - protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None): + protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None, business_connection_id=None): method_url = get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -923,6 +950,8 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['emoji'] = emoji if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1376,7 +1405,7 @@ def delete_message(token, chat_id, message_id, timeout=None): def send_game( token, chat_id, game_short_name, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None, reply_parameters=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: @@ -1391,6 +1420,8 @@ def send_game( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) @@ -1779,7 +1810,8 @@ def send_poll( question, options, is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, - reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None): + reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, + business_connection_id=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1822,6 +1854,8 @@ def send_poll( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if business_connection_id is not None: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 37dc712bc..f5f3a16fe 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3035,7 +3035,8 @@ async def send_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - link_preview_options: Optional[types.LinkPreviewOptions]=None) -> types.Message: + link_preview_options: Optional[types.LinkPreviewOptions]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send text messages. @@ -3088,6 +3089,9 @@ async def send_message( :param link_preview_options: Options for previewing links. :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3142,7 +3146,7 @@ async def send_message( await asyncio_helper.send_message( self.token, chat_id, text, reply_markup, parse_mode, disable_notification, timeout, - entities, protect_content, message_thread_id, reply_parameters, link_preview_options)) + entities, protect_content, message_thread_id, reply_parameters, link_preview_options, business_connection_id)) async def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -3415,7 +3419,8 @@ async def send_dice( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -3454,6 +3459,9 @@ async def send_dice( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3484,8 +3492,8 @@ async def send_dice( return types.Message.de_json( await asyncio_helper.send_dice( self.token, chat_id, emoji, disable_notification, - reply_markup, timeout, protect_content, message_thread_id, reply_parameters) - ) + reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id)) + async def send_photo( self, chat_id: Union[int, str], photo: Union[Any, str], @@ -3499,7 +3507,8 @@ async def send_photo( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -3550,6 +3559,9 @@ async def send_photo( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3583,7 +3595,7 @@ async def send_photo( await asyncio_helper.send_photo( self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, has_spoiler, reply_parameters)) + protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id)) async def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -3600,7 +3612,8 @@ async def send_audio( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -3670,6 +3683,9 @@ async def send_audio( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3706,7 +3722,7 @@ async def send_audio( await asyncio_helper.send_audio( self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, protect_content, message_thread_id, reply_parameters)) + caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id)) async def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], @@ -3720,7 +3736,8 @@ async def send_voice( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). @@ -3773,6 +3790,9 @@ async def send_voice( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -3804,7 +3824,7 @@ async def send_voice( await asyncio_helper.send_voice( self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, reply_parameters)) + protect_content, message_thread_id, reply_parameters, business_connection_id)) async def send_document( self, chat_id: Union[int, str], document: Union[Any, str], @@ -3823,7 +3843,8 @@ async def send_document( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send general files. @@ -3886,6 +3907,9 @@ async def send_document( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3930,7 +3954,7 @@ async def send_document( disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content, - message_thread_id = message_thread_id, reply_parameters=reply_parameters)) + message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) async def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], @@ -3943,7 +3967,8 @@ async def send_sticker( data: Union[Any, str]=None, message_thread_id: Optional[int]=None, emoji: Optional[str]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -3989,6 +4014,9 @@ async def send_sticker( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Unique identifier for the target business connection + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4027,7 +4055,7 @@ async def send_sticker( reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters)) + message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) async def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -4049,7 +4077,8 @@ async def send_video( message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4120,6 +4149,9 @@ async def send_video( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4161,7 +4193,7 @@ async def send_video( await asyncio_helper.send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, - caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters)) + caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -4181,7 +4213,8 @@ async def send_animation( message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -4251,6 +4284,9 @@ async def send_animation( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4287,7 +4323,7 @@ async def send_animation( await asyncio_helper.send_animation( self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters)) + caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -4302,7 +4338,8 @@ async def send_video_note( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -4357,6 +4394,9 @@ async def send_video_note( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4391,7 +4431,7 @@ async def send_video_note( return types.Message.de_json( await asyncio_helper.send_video_note( self.token, chat_id, data, duration, length, reply_markup, - disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters)) + disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id)) async def send_media_group( self, chat_id: Union[int, str], @@ -4404,7 +4444,8 @@ async def send_media_group( timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> List[types.Message]: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -4438,6 +4479,9 @@ async def send_media_group( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -4466,7 +4510,7 @@ async def send_media_group( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = await asyncio_helper.send_media_group( - self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters) + self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id) return [types.Message.de_json(msg) for msg in result] async def send_location( @@ -4483,7 +4527,8 @@ async def send_location( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -4536,6 +4581,9 @@ async def send_location( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4568,7 +4616,7 @@ async def send_location( self.token, chat_id, latitude, longitude, live_period, reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, - protect_content, message_thread_id, reply_parameters)) + protect_content, message_thread_id, reply_parameters, business_connection_id)) async def edit_message_live_location( self, latitude: float, longitude: float, @@ -4677,7 +4725,8 @@ async def send_venue( google_place_type: Optional[str]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -4738,6 +4787,9 @@ async def send_venue( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4769,8 +4821,8 @@ async def send_venue( await asyncio_helper.send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, disable_notification, reply_markup, timeout, - google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters) - ) + google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id)) + async def send_contact( self, chat_id: Union[int, str], phone_number: str, @@ -4783,7 +4835,8 @@ async def send_contact( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -4831,6 +4884,9 @@ async def send_contact( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4862,8 +4918,8 @@ async def send_contact( await asyncio_helper.send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters) - ) + protect_content, message_thread_id, reply_parameters, business_connection_id)) + async def send_chat_action( self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None) -> bool: @@ -5968,7 +6024,8 @@ async def send_game( allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Used to send the game. @@ -6004,6 +6061,9 @@ async def send_game( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of the business connection. + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6034,7 +6094,7 @@ async def send_game( result = await asyncio_helper.send_game( self.token, chat_id, game_short_name, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters) + protect_content, message_thread_id, reply_parameters, business_connection_id) return types.Message.de_json(result) async def set_game_score( @@ -6396,7 +6456,8 @@ async def send_poll( explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -6470,6 +6531,9 @@ async def send_poll( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param business_connection_id: Identifier of the business connection to send the message through + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6508,7 +6572,7 @@ async def send_poll( is_anonymous, type, allows_multiple_answers, correct_option_id, explanation, explanation_parse_mode, open_period, close_date, is_closed, disable_notification, - reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters)) + reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters, business_connection_id)) async def stop_poll( self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index ceafe637f..186abf904 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -281,7 +281,7 @@ async def send_message( reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, - message_thread_id=None, reply_parameters=None, link_preview_options=None): + message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -302,6 +302,8 @@ async def send_message( params['protect_content'] = protect_content if message_thread_id: params['message_thread_id'] = message_thread_id + if business_connection_id: + params['business_connection_id'] = business_connection_id return await _process_request(token, method_name, params=params) @@ -433,7 +435,7 @@ async def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, - message_thread_id=None,reply_parameters=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -450,6 +452,8 @@ async def send_dice( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) @@ -458,7 +462,8 @@ async def send_photo( caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None,reply_parameters=None): + message_thread_id=None, has_spoiler=None,reply_parameters=None, + business_connection_id=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -488,13 +493,15 @@ async def send_photo( payload['message_thread_id'] = message_thread_id if has_spoiler is not None: payload['has_spoiler'] = has_spoiler + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_media_group( token, chat_id, media, disable_notification=None, - timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None): + timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendMediaGroup' media_json, files = await convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -508,6 +515,8 @@ async def send_media_group( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request( token, method_url, params=payload, method='post' if files else 'get', @@ -519,7 +528,7 @@ async def send_location( live_period=None, reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, - proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None): + proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -542,6 +551,8 @@ async def send_location( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) @@ -593,7 +604,7 @@ async def send_venue( foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, - google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None): + google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -616,13 +627,15 @@ async def send_venue( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) async def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None,reply_parameters=None): + protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -641,6 +654,8 @@ async def send_contact( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) @@ -657,7 +672,7 @@ async def send_chat_action(token, chat_id, action, timeout=None, message_thread_ async def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, - protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None): + protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -701,6 +716,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['message_thread_id'] = message_thread_id if has_spoiler is not None: payload['has_spoiler'] = has_spoiler + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -708,7 +725,7 @@ async def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, width=None, height=None, protect_content=None, message_thread_id=None, - has_spoiler=None,reply_parameters=None): + has_spoiler=None,reply_parameters=None, business_connection_id=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -750,12 +767,14 @@ async def send_animation( payload['message_thread_id'] = message_thread_id if has_spoiler is not None: payload['has_spoiler'] = has_spoiler + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - protect_content=None, message_thread_id=None,reply_parameters=None): + protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -783,12 +802,14 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_ payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None,reply_parameters=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -822,12 +843,14 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, rep payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, - caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None): + caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -867,13 +890,15 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None, - message_thread_id=None, emoji=None,reply_parameters=None): + message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None): method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -914,6 +939,8 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m payload['message_thread_id'] = message_thread_id if emoji: payload['emoji'] = emoji + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1363,7 +1390,7 @@ async def delete_message(token, chat_id, message_id, timeout=None): async def send_game( token, chat_id, game_short_name, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None,reply_parameters=None): + protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: @@ -1378,6 +1405,8 @@ async def send_game( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) @@ -1763,7 +1792,7 @@ async def send_poll( is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, - reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None): + reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1807,6 +1836,8 @@ async def send_poll( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) diff --git a/telebot/types.py b/telebot/types.py index fbb857ae0..7119003fa 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -225,7 +225,7 @@ def de_json(cls, json_string): return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, - business_connection, business_message, edited_business_message, deleted_business_messages, **obj) + business_connection, business_message, edited_business_message, deleted_business_messages) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, From 60f91937ecdddd1a5f2c15a44bab11ace86da806 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:14:24 +0500 Subject: [PATCH 179/480] Fix parantheses and add business connection to sendchataction --- telebot/__init__.py | 12 ++++++++---- telebot/apihelper.py | 4 +++- telebot/async_telebot.py | 8 ++++++-- telebot/asyncio_helper.py | 4 +++- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 291b77ead..ccb98f0b8 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2093,7 +2093,7 @@ def send_dice( self.token, chat_id, emoji=emoji, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) - ) + def send_photo( @@ -2195,7 +2195,7 @@ def send_photo( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) - ) + def send_audio( @@ -3517,7 +3517,8 @@ def send_contact( def send_chat_action( - self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None) -> bool: + self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, + business_connection_id: Optional[str]=None) -> bool: """ Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). @@ -3543,11 +3544,14 @@ def send_chat_action( :param message_thread_id: The thread identifier of a message from which the reply will be sent(supergroups only) :type message_thread_id: :obj:`int` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: Returns True on success. :rtype: :obj:`bool` """ return apihelper.send_chat_action( - self.token, chat_id, action, timeout=timeout, message_thread_id=message_thread_id) + self.token, chat_id, action, timeout=timeout, message_thread_id=message_thread_id, business_connection_id=business_connection_id) @util.deprecated(deprecation_text="Use ban_chat_member instead") diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 93632ac05..af2972e04 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -669,13 +669,15 @@ def send_contact( return _make_request(token, method_url, params=payload) -def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=None): +def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=None, business_connection_id=None): method_url = r'sendChatAction' payload = {'chat_id': chat_id, 'action': action} if timeout: payload['timeout'] = timeout if message_thread_id is not None: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index f5f3a16fe..1cf75f30e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4922,7 +4922,8 @@ async def send_contact( async def send_chat_action( - self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None) -> bool: + self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, + business_connection_id: Optional[str]=None) -> bool: """ Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). @@ -4948,10 +4949,13 @@ async def send_chat_action( :param message_thread_id: The thread to which the message will be sent(supergroups only) :type message_thread_id: :obj:`int` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.send_chat_action(self.token, chat_id, action, timeout, message_thread_id) + return await asyncio_helper.send_chat_action(self.token, chat_id, action, timeout, message_thread_id, business_connection_id) async def kick_chat_member( self, chat_id: Union[int, str], user_id: int, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 186abf904..3a90cb41d 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -659,13 +659,15 @@ async def send_contact( return await _process_request(token, method_url, params=payload) -async def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=None): +async def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=None, business_connection_id=None): method_url = r'sendChatAction' payload = {'chat_id': chat_id, 'action': action} if timeout: payload['timeout'] = timeout if message_thread_id: payload['message_thread_id'] = message_thread_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) From c9ceab76fb05599b21538979aec457a7a74077e0 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:20:27 +0500 Subject: [PATCH 180/480] fix --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 7119003fa..ac5ab32fd 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -220,7 +220,7 @@ def de_json(cls, json_string): business_connection = BusinessConnection.de_json(obj.get('business_connection')) business_message = Message.de_json(obj.get('business_message')) edited_business_message = Message.de_json(obj.get('edited_business_message')) - deleted_business_messages = Message.de_json(obj.get('deleted_business_messages')) + deleted_business_messages = BusinessMessagesDeleted.de_json(obj.get('deleted_business_messages')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, From a151b78beb0baa33dfcbe31a016e81a1faa0fba1 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:25:58 +0500 Subject: [PATCH 181/480] added sender_business_bot and business_connection_id --- telebot/types.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index ac5ab32fd..82b081aff 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -843,9 +843,16 @@ class Message(JsonDeserializable): :param sender_boost_count: Optional. If the sender of the message boosted the chat, the number of boosts added by the user :type sender_boost_count: :obj:`int` + :param sender_business_bot info: Optional. Information about the business bot that sent the message + :type sender_business_bot_info: :class:`telebot.types.User` + :param date: Date the message was sent in Unix time :type date: :obj:`int` + :param business_connection_id: Optional. Unique identifier of the business connection from which the message was received. If non-empty, + the message belongs to a chat of the corresponding business account that is independent from any potential bot chat which might share the same identifier. + :type business_connection_id: :obj:`str` + :param chat: Conversation the message belongs to :type chat: :class:`telebot.types.Chat` @@ -1326,6 +1333,11 @@ def de_json(cls, json_string): opts['sender_boost_count'] = obj['sender_boost_count'] if 'reply_to_story' in obj: opts['reply_to_story'] = Story.de_json(obj['reply_to_story']) + if 'sender_business_bot' in obj: + opts['sender_business_bot'] = User.de_json(obj['sender_business_bot']) + if 'business_connection_id' in obj: + opts['business_connection_id'] = obj['business_connection_id'] + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1430,6 +1442,8 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.boost_added: Optional[ChatBoostAdded] = None self.sender_boost_count: Optional[int] = None self.reply_to_story: Optional[Story] = None + self.sender_business_bot: Optional[User] = None + self.business_connection_id: Optional[str] = None for key in options: setattr(self, key, options[key]) From 95b38ae7a87878091d456fa1afe5f79eb9e2361c Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:40:18 +0500 Subject: [PATCH 182/480] added business things --- telebot/__init__.py | 4 +- telebot/async_telebot.py | 4 +- telebot/types.py | 142 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 144 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index ccb98f0b8..269136402 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -8208,7 +8208,7 @@ def deleted_business_messages_handler(self, func=None, **kwargs): def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) - self.add_deleted_message_handler(handler_dict) + self.add_deleted_business_messages_handler(handler_dict) return handler return decorator @@ -8220,7 +8220,7 @@ def add_deleted_business_messages_handler(self, handler_dict): :meta private: """ - self.deleted_message_handlers.append(handler_dict) + self.deleted_business_messages_handlers.append(handler_dict) def register_deleted_business_messages_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 1cf75f30e..16128ba10 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2484,7 +2484,7 @@ def deleted_business_messages_handler(self, func=None, **kwargs): def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) - self.add_deleted_message_handler(handler_dict) + self.add_deleted_business_messages_handler(handler_dict) return handler return decorator @@ -2496,7 +2496,7 @@ def add_deleted_business_messages_handler(self, handler_dict): :meta private: """ - self.deleted_message_handlers.append(handler_dict) + self.deleted_business_messages_handlers.append(handler_dict) def register_deleted_business_messages_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ diff --git a/telebot/types.py b/telebot/types.py index 82b081aff..d8afbdf52 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -584,6 +584,15 @@ class Chat(JsonDeserializable): Returned only in getChat. :type active_usernames: :obj:`list` of :obj:`str` + :param business_intro: Optional. Business intro for the chat. Returned only in getChat. + :type business_intro: :class:`telebot.types.BusinessIntro` + + :param business_location: Optional. Business location for the chat. Returned only in getChat. + :type business_location: :class:`telebot.types.BusinessLocation` + + :param business_opening_hours : Optional. Business opening hours for the chat. Returned only in getChat. + :type business_opening_hours: :class:`telebot.types.BusinessHours` + :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels. Returned only in getChat. :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType` @@ -711,6 +720,12 @@ def de_json(cls, json_string): obj['location'] = ChatLocation.de_json(obj['location']) if 'available_reactions' in obj: obj['available_reactions'] = [ReactionType(reaction) for reaction in obj['available_reactions']] + if 'business_intro' in obj: + obj['business_intro'] = BusinessIntro.de_json(obj['business_intro']) + if 'business_location' in obj: + obj['business_location'] = BusinessLocation.de_json(obj['business_location']) + if 'business_opening_hours' in obj: + obj['business_opening_hours'] = BusinessOpeningHours.de_json(obj['business_opening_hours']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -724,7 +739,8 @@ def __init__(self, id, type, title=None, username=None, first_name=None, has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, profile_background_custom_emoji_id=None, has_visible_history=None, - unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, **kwargs): + unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, + business_opening_hours=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -762,6 +778,9 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.has_visible_history: bool = has_visible_history self.unrestrict_boost_count: int = unrestrict_boost_count self.custom_emoji_sticker_set_name: str = custom_emoji_sticker_set_name + self.business_intro: BusinessIntro = business_intro + self.business_location: BusinessLocation = business_location + self.business_opening_hours: BusinessOpeningHours = business_opening_hours @@ -9425,4 +9444,123 @@ def __init__(self, business_connection_id, chat, message_ids, **kwargs): self.business_connection_id: str = business_connection_id self.chat: Chat = chat self.message_ids: List[int] = message_ids - \ No newline at end of file + + +class BusinessIntro(JsonDeserializable): + """ + This object represents a business intro. + + Telegram documentation: https://core.telegram.org/bots/api#businessintro + + :param title: Optional. Title text of the business intro + :type title: :obj:`str` + + :param message: Optional. Message text of the business intro + :type message: :obj:`str` + + :param sticker: Optional. Sticker of the business intro + :type sticker: :class:`Sticker` + + :return: Instance of the class + :rtype: :class:`BusinessIntro` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'sticker' in obj: + obj['sticker'] = Sticker.de_json(obj['sticker']) + return cls(**obj) + + def __init__(self, title=None, message=None, sticker=None, **kwargs): + self.title: Optional[str] = title + self.message: Optional[str] = message + self.sticker: Optional[Sticker] = sticker + + +class BusinessLocation(JsonDeserializable): + """ + This object represents a business location. + + Telegram documentation: https://core.telegram.org/bots/api#businesslocation + + :param address: Address of the business + :type address: :obj:`str` + + :param location: Optional. Location of the business + :type location: :class:`Location` + + :return: Instance of the class + :rtype: :class:`BusinessLocation` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'location' in obj: + obj['location'] = Location.de_json(obj['location']) + return cls(**obj) + + def __init__(self, address, location=None, **kwargs): + self.address: str = address + self.location: Optional[Location] = location + + +class BusinessOpeningHoursInterval(JsonDeserializable): + """ + This object represents a business opening hours interval. + + Telegram documentation: https://core.telegram.org/bots/api#businessopeninghoursinterval + + :param opening_minute: The minute's sequence number in a week, starting on Monday, marking the start of the time interval during which the business is open; 0 - 7 24 60 + :type opening_minute: :obj:`int` + + :param closing_minute: The minute's sequence number in a week, starting on Monday, marking the end of the time interval during which the business is open; 0 - 8 24 60 + :type closing_minute: :obj:`int` + + :return: Instance of the class + :rtype: :class:`BusinessOpeningHoursInterval` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, opening_minute, closing_minute, **kwargs): + self.opening_minute: int = opening_minute + self.closing_minute: int = closing_minute + + +class BusinessOpeningHours(JsonDeserializable): + """ + + This object represents business opening hours. + + Telegram documentation: https://core.telegram.org/bots/api#businessopeninghours + + :param time_zone_name: Unique name of the time zone for which the opening hours are defined + :type time_zone_name: :obj:`str` + + :param opening_hours: List of time intervals describing business opening hours + :type opening_hours: :obj:`list` of :class:`BusinessOpeningHoursInterval` + + :return: Instance of the class + + :rtype: :class:`BusinessOpeningHours` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['opening_hours'] = [BusinessOpeningHoursInterval.de_json(interval) for interval in obj['opening_hours']] + return cls(**obj) + + def __init__(self, time_zone_name, opening_hours, **kwargs): + self.time_zone_name: str = time_zone_name + self.opening_hours: List[BusinessOpeningHoursInterval] = opening_hours + From 63de545fab5d51dc2304c9b9c898b4505060b3b8 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:50:56 +0500 Subject: [PATCH 183/480] Added the field format to the class InputSticker. --- telebot/types.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index d8afbdf52..2dfc69c66 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7950,15 +7950,19 @@ class InputSticker(Dictionaryable, JsonSerializable): For “regular” and “custom_emoji” stickers only. :type keywords: :obj:`list` of :obj:`str` + :param format: Format of the added sticker, must be one of “static” for a .WEBP or .PNG image, “animated” for a .TGS animation, “video” for a WEBM video + :type format: :obj:`str` + :return: Instance of the class :rtype: :class:`telebot.types.InputSticker` """ - def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], mask_position: Optional[MaskPosition]=None, keywords: Optional[List[str]]=None) -> None: + def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], format: str, mask_position: Optional[MaskPosition]=None, keywords: Optional[List[str]]=None) -> None: self.sticker: Union[str, InputFile] = sticker self.emoji_list: List[str] = emoji_list self.mask_position: Optional[MaskPosition] = mask_position self.keywords: Optional[List[str]] = keywords + self.format: str = format if service_utils.is_string(self.sticker): self._sticker_name = '' @@ -7973,7 +7977,8 @@ def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], mask_p def to_dict(self) -> dict: json_dict = { 'sticker': self._sticker_dic, - 'emoji_list': self.emoji_list + 'emoji_list': self.emoji_list, + 'format': self.format } if self.mask_position is not None: From 4ed9b03aa2ec6d36b8c3ef9e43aeb6238d0c5ca3 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 01:55:32 +0500 Subject: [PATCH 184/480] added format to set sticker thumbnail --- telebot/__init__.py | 7 +++++-- telebot/apihelper.py | 4 ++-- telebot/async_telebot.py | 4 ++-- telebot/asyncio_helper.py | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 269136402..2007775d5 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5543,7 +5543,7 @@ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types. ) - def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None): + def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, thumbnail: Union[Any, str]=None): """ Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. @@ -5559,10 +5559,13 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[An :param thumbnail: A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. :type thumbnail: :obj:`filelike object` + :param format: Format of the thumbnail, must be one of “static” for a .WEBP or .PNG image, “animated” for a .TGS animation, or “video” for a WEBM video + :type format: :obj:`str` + :return: On success, True is returned. :rtype: :obj:`bool` """ - return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail) + return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") diff --git a/telebot/apihelper.py b/telebot/apihelper.py index af2972e04..530257ff6 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -371,9 +371,9 @@ def get_chat_member_count(token, chat_id): return _make_request(token, method_url, params=payload) -def set_sticker_set_thumbnail(token, name, user_id, thumbnail): +def set_sticker_set_thumbnail(token, name, user_id, thumbnail, format): method_url = r'setStickerSetThumbnail' - payload = {'name': name, 'user_id': user_id} + payload = {'name': name, 'user_id': user_id, 'format': format} files = {} if thumbnail: if not isinstance(thumbnail, str): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 16128ba10..8af0c4d1d 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6866,7 +6866,7 @@ async def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> return types.UserChatBoosts.de_json(result) - async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None): + async def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, thumbnail: Union[Any, str]=None): """ Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. @@ -6885,7 +6885,7 @@ async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Un :return: On success, True is returned. :rtype: :obj:`bool` """ - return await asyncio_helper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail) + return await asyncio_helper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") async def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]=None): diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 3a90cb41d..40ef2927c 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -352,15 +352,16 @@ async def get_chat_member_count(token, chat_id): return await _process_request(token, method_url, params=payload) -async def set_sticker_set_thumbnail(token, name, user_id, thumbnail): +async def set_sticker_set_thumbnail(token, name, user_id, thumbnail, format): method_url = r'setStickerSetThumbnail' - payload = {'name': name, 'user_id': user_id} + payload = {'name': name, 'user_id': user_id, 'format': format} files = {} if thumbnail: if not isinstance(thumbnail, str): files['thumbnail'] = thumbnail else: payload['thumbnail'] = thumbnail + return await _process_request(token, method_url, params=payload, files=files or None) From d187aec77639014096f95976212a7bffc4e5e47c Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:02:05 +0500 Subject: [PATCH 185/480] added requests to sharing chats --- telebot/types.py | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 2dfc69c66..2c96560c1 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2578,16 +2578,29 @@ class KeyboardButtonRequestUsers(Dictionaryable): :param max_quantity: Optional. The maximum number of users to be selected; 1-10. Defaults to 1. :type max_quantity: :obj:`int` + :param request_name: Optional. Request name + :type request_name: :obj:`bool` + + :param request_username: Optional. Request username + :type request_username: :obj:`bool` + + :param request_photo: Optional. Request photo + :type request_photo: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.KeyboardButtonRequestUsers` """ def __init__( self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, - max_quantity: Optional[int]=None) -> None: + max_quantity: Optional[int]=None, request_name: Optional[str]=None, request_username: Optional[bool]=None, + request_photo: Optional[bool]=None) -> None: self.request_id: int = request_id self.user_is_bot: Optional[bool] = user_is_bot self.user_is_premium: Optional[bool] = user_is_premium self.max_quantity: Optional[int] = max_quantity + self.request_name: Optional[str] = request_name + self.request_username: Optional[bool] = request_username + self.request_photo: Optional[bool] = request_photo def to_dict(self) -> dict: data = {'request_id': self.request_id} @@ -2597,6 +2610,12 @@ def to_dict(self) -> dict: data['user_is_premium'] = self.user_is_premium if self.max_quantity is not None: data['max_quantity'] = self.max_quantity + if self.request_name is not None: + data['request_name'] = self.request_name + if self.request_username is not None: + data['request_username'] = self.request_username + if self.request_photo is not None: + data['request_photo'] = self.request_photo return data @@ -2645,6 +2664,15 @@ class KeyboardButtonRequestChat(Dictionaryable): :param bot_is_member: Optional. Pass True to request a chat where the bot is a member. Otherwise, no additional restrictions are applied. :type bot_is_member: :obj:`bool` + :param request_title: Optional. Request title + :type request_title: :obj:`bool` + + :param request_photo: Optional. Request photo + :type request_photo: :obj:`bool` + + :param request_username: Optional. Request username + :type request_username: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.KeyboardButtonRequestChat` """ @@ -2652,7 +2680,8 @@ class KeyboardButtonRequestChat(Dictionaryable): def __init__(self, request_id: int, chat_is_channel: bool, chat_is_forum: Optional[bool]=None, chat_has_username: Optional[bool]=None, chat_is_created: Optional[bool]=None, user_administrator_rights: Optional[ChatAdministratorRights]=None, - bot_administrator_rights: Optional[ChatAdministratorRights]=None, bot_is_member: Optional[bool]=None) -> None: + bot_administrator_rights: Optional[ChatAdministratorRights]=None, bot_is_member: Optional[bool]=None, + request_title: Optional[str]=None, request_photo: Optional[bool]=None, request_username: Optional[bool]=None): self.request_id: int = request_id self.chat_is_channel: bool = chat_is_channel self.chat_is_forum: Optional[bool] = chat_is_forum @@ -2661,6 +2690,9 @@ def __init__(self, request_id: int, chat_is_channel: bool, chat_is_forum: Option self.user_administrator_rights: Optional[ChatAdministratorRights] = user_administrator_rights self.bot_administrator_rights: Optional[ChatAdministratorRights] = bot_administrator_rights self.bot_is_member: Optional[bool] = bot_is_member + self.request_title: Optional[str] = request_title + self.request_photo: Optional[bool] = request_photo + self.request_username: Optional[bool] = request_username def to_dict(self) -> dict: @@ -2677,6 +2709,12 @@ def to_dict(self) -> dict: data['bot_administrator_rights'] = self.bot_administrator_rights.to_dict() if self.bot_is_member is not None: data['bot_is_member'] = self.bot_is_member + if self.request_title is not None: + data['request_title'] = self.request_title + if self.request_photo is not None: + data['request_photo'] = self.request_photo + if self.request_username is not None: + data['request_username'] = self.request_username return data From 33dbe9c88780ab93dedbeabe3503c26784898912 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:07:14 +0500 Subject: [PATCH 186/480] Added the class SharedUser and replaced the field user_ids in the class UsersShared with the field users. --- telebot/types.py | 49 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 2c96560c1..6ade97704 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9043,13 +9043,13 @@ class UsersShared(JsonDeserializable): :param request_id: Identifier of the request :type request_id: :obj:`int` - :param user_ids: Identifiers of the shared users. These numbers may have more than 32 significant bits + :param user_ids: Array of :obj:`types.SharedUser` of the shared users. These numbers may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting them. But they have at most 52 significant bits, so 64-bit integers or double-precision float types are safe for storing these identifiers. The bot may not have access to the users and could be unable to use these identifiers unless the users are already known to the bot by some other means. - :type user_ids: :obj:`list` of :obj:`int` + :type user_ids: :obj:`list` of :obj:`types.SharedUser` :return: Instance of the class :rtype: :class:`UsersShared` @@ -9058,9 +9058,12 @@ class UsersShared(JsonDeserializable): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) + + obj['user_ids'] = [SharedUser.de_json(user) for user in obj['user_ids']] + return cls(**obj) - def __init__(self, request_id, user_ids, **kwargs): + def __init__(self, request_id, user_ids: SharedUser, **kwargs): self.request_id = request_id self.user_ids = user_ids @@ -9607,3 +9610,43 @@ def __init__(self, time_zone_name, opening_hours, **kwargs): self.time_zone_name: str = time_zone_name self.opening_hours: List[BusinessOpeningHoursInterval] = opening_hours + +class SharedUser(JsonDeserializable): + """ + This object contains information about a user that was shared with the bot using a KeyboardButtonRequestUser button. + + Telegram documentation: https://core.telegram.org/bots/api#shareduser + + :param user_id: Identifier of the shared user. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so 64-bit integers or double-precision float types are safe for storing these identifiers. The bot may not have access to the user and could be unable to use this identifier, unless the user is already known to the bot by some other means. + :type user_id: :obj:`int` + + :param first_name: Optional. First name of the user, if the name was requested by the bot + :type first_name: :obj:`str` + + :param last_name: Optional. Last name of the user, if the name was requested by the bot + :type last_name: :obj:`str` + + :param username: Optional. Username of the user, if the username was requested by the bot + :type username: :obj:`str` + + :param photo: Optional. Available sizes of the chat photo, if the photo was requested by the bot + :type photo: :obj:`list` of :class:`PhotoSize` + + :return: Instance of the class + :rtype: :class:`SharedUser` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'photo' in obj: + obj['photo'] = [PhotoSize.de_json(photo) for photo in obj['photo']] + return cls(**obj) + + def __init__(self, user_id, first_name=None, last_name=None, username=None, photo=None, **kwargs): + self.user_id: int = user_id + self.first_name: Optional[str] = first_name + self.last_name: Optional[str] = last_name + self.username: Optional[str] = username + self.photo: Optional[List[PhotoSize]] = photo From 63d09f5fff6f48e88de4e92a89fdbebb28289d8f Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:15:09 +0500 Subject: [PATCH 187/480] Added the fields title, username, and photo to the class ChatShared. --- telebot/types.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 6ade97704..29d2b7432 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7908,6 +7908,15 @@ class ChatShared(JsonDeserializable): and could be unable to use this identifier, unless the chat is already known to the bot by some other means. :type chat_id: :obj:`int` + :param title: Optional. Title of the shared chat + :type title: :obj:`str` + + :param photo: Optional. Array of Photosize + :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` + + :param username: Optional. Username of the shared chat + :type username: :obj:`str` + :return: Instance of the class :rtype: :class:`telebot.types.ChatShared` """ @@ -7918,9 +7927,13 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, request_id: int, chat_id: int, **kwargs) -> None: + def __init__(self, request_id: int, chat_id: int, title: Optional[str]=None, photo: Optional[List[PhotoSize]]=None, + username: Optional[str]=None, **kwargs) -> None: self.request_id: int = request_id self.chat_id: int = chat_id + self.title: Optional[str] = title + self.photo: Optional[List[PhotoSize]] = photo + self.username: Optional[str] = username class BotDescription(JsonDeserializable): From 1717f0dd0f2ffe26cd469425e31580c2e6e0dcd6 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:17:22 +0500 Subject: [PATCH 188/480] Added the field is_from_offline to the class Message. --- telebot/types.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 29d2b7432..a61613022 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -926,6 +926,10 @@ class Message(JsonDeserializable): :param has_protected_content: Optional. :obj:`bool`, if the message can't be forwarded :type has_protected_content: :obj:`bool` + :param is_from_offline: Optional. True, if the message was sent by an implicit action, for example, + as an away or a greeting business message, or as a scheduled message + :type is_from_offline: :obj:`bool` + :param media_group_id: Optional. The unique identifier of a media message group this message belongs to :type media_group_id: :obj:`str` @@ -1356,6 +1360,8 @@ def de_json(cls, json_string): opts['sender_business_bot'] = User.de_json(obj['sender_business_bot']) if 'business_connection_id' in obj: opts['business_connection_id'] = obj['business_connection_id'] + if 'is_from_offline' in obj: + opts['is_from_offline'] = obj['is_from_offline'] @@ -1463,6 +1469,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.reply_to_story: Optional[Story] = None self.sender_business_bot: Optional[User] = None self.business_connection_id: Optional[str] = None + self.is_from_offline: Optional[bool] = None for key in options: setattr(self, key, options[key]) From f2344d262d1225cbbd4bd700c0345231dce6bfff Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:20:27 +0500 Subject: [PATCH 189/480] can_connect_to_business and personal_chat --- telebot/types.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index a61613022..0db7c2159 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -481,6 +481,9 @@ class User(JsonDeserializable, Dictionaryable, JsonSerializable): :param supports_inline_queries: Optional. True, if the bot supports inline queries. Returned only in getMe. :type supports_inline_queries: :obj:`bool` + :param can_connect_to_business: Optional. True, if the bot can be connected to a Telegram Business account to receive its messages. Returned only in getMe. + :type can_connect_to_business: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.User` """ @@ -492,7 +495,7 @@ def de_json(cls, json_string): def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, - is_premium=None, added_to_attachment_menu=None, **kwargs): + is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, **kwargs): self.id: int = id self.is_bot: bool = is_bot self.first_name: str = first_name @@ -504,6 +507,7 @@ def __init__(self, id, is_bot, first_name, last_name=None, username=None, langua self.supports_inline_queries: bool = supports_inline_queries self.is_premium: bool = is_premium self.added_to_attachment_menu: bool = added_to_attachment_menu + self.can_connect_to_business: bool = can_connect_to_business @property @@ -530,7 +534,9 @@ def to_dict(self): 'can_read_all_group_messages': self.can_read_all_group_messages, 'supports_inline_queries': self.supports_inline_queries, 'is_premium': self.is_premium, - 'added_to_attachment_menu': self.added_to_attachment_menu} + 'added_to_attachment_menu': self.added_to_attachment_menu, + 'can_connect_to_business': self.can_connect_to_business} + class GroupChat(JsonDeserializable): @@ -593,6 +599,9 @@ class Chat(JsonDeserializable): :param business_opening_hours : Optional. Business opening hours for the chat. Returned only in getChat. :type business_opening_hours: :class:`telebot.types.BusinessHours` + :param personal_chat: Optional. For private chats, the personal channel of the user. Returned only in getChat. + :type personal_chat: :class:`telebot.types.Chat` + :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels. Returned only in getChat. :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType` @@ -726,6 +735,8 @@ def de_json(cls, json_string): obj['business_location'] = BusinessLocation.de_json(obj['business_location']) if 'business_opening_hours' in obj: obj['business_opening_hours'] = BusinessOpeningHours.de_json(obj['business_opening_hours']) + if 'personal_chat' in obj: + obj['personal_chat'] = Chat.de_json(obj['personal_chat']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -740,7 +751,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, - business_opening_hours=None, **kwargs): + business_opening_hours=None, personal_chat=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -781,6 +792,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.business_intro: BusinessIntro = business_intro self.business_location: BusinessLocation = business_location self.business_opening_hours: BusinessOpeningHours = business_opening_hours + self.personal_chat: Chat = personal_chat From a7c94fa40fe2f441c102a25c78d796fb20cbb1f5 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:24:10 +0500 Subject: [PATCH 190/480] replacestickerinset --- telebot/__init__.py | 25 +++++++++++++++++++++++++ telebot/apihelper.py | 5 +++++ telebot/async_telebot.py | 24 ++++++++++++++++++++++++ telebot/asyncio_helper.py | 6 ++++++ 4 files changed, 60 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 2007775d5..0d6e2aba0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5705,6 +5705,31 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) + + def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, sticker: types.InputSticker) -> bool: + """ + Use this method to replace an existing sticker in a sticker set with a new one. The method is equivalent to calling deleteStickerFromSet, then addStickerToSet, + then setStickerPositionInSet. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#replaceStickerInSet + + :param user_id: User identifier of the sticker set owner + :type user_id: :obj:`int` + + :param name: Sticker set name + :type name: :obj:`str` + + :param old_sticker: File identifier of the replaced sticker + :type old_sticker: :obj:`str` + + :param sticker: A JSON-serialized object with information about the added sticker. If exactly the same sticker had already been added to the set, then the set remains unchanged. + :type sticker: :class:`telebot.types.InputSticker` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.replace_sticker_in_set(self.token, user_id, name, old_sticker, sticker) + def set_sticker_emoji_list(self, sticker: str, emoji_list: List[str]) -> bool: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 530257ff6..1b3a6df99 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -383,6 +383,11 @@ def set_sticker_set_thumbnail(token, name, user_id, thumbnail, format): return _make_request(token, method_url, params=payload, files=files or None) +def replace_sticker_in_set(token, user_id, name, old_sticker, sticker): + method_url = r'replaceStickerInSet' + payload = {'user_id': user_id, 'name': name, 'old_sticker': old_sticker, 'sticker': sticker.to_json()} + return _make_request(token, method_url, params=payload) + def set_chat_sticker_set(token, chat_id, sticker_set_name): method_url = r'setChatStickerSet' payload = {'chat_id': chat_id, 'sticker_set_name': sticker_set_name} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8af0c4d1d..57ae8e6a4 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7051,6 +7051,30 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) + async def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, sticker: types.InputSticker) -> bool: + """ + Use this method to replace an existing sticker in a sticker set with a new one. The method is equivalent to calling deleteStickerFromSet, then addStickerToSet, + then setStickerPositionInSet. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#replaceStickerInSet + + :param user_id: User identifier of the sticker set owner + :type user_id: :obj:`int` + + :param name: Sticker set name + :type name: :obj:`str` + + :param old_sticker: File identifier of the replaced sticker + :type old_sticker: :obj:`str` + + :param sticker: A JSON-serialized object with information about the added sticker. If exactly the same sticker had already been added to the set, then the set remains unchanged. + :type sticker: :class:`telebot.types.InputSticker` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + result = await asyncio_helper.replace_sticker_in_set(self.token, user_id, name, old_sticker, sticker) + return result async def set_sticker_emoji_list(self, name: str, emoji_list: List[str]) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 40ef2927c..e1fcdec36 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -352,6 +352,12 @@ async def get_chat_member_count(token, chat_id): return await _process_request(token, method_url, params=payload) + +async def replace_sticker_in_set(token, user_id, name, old_sticker, sticker): + method_url = r'replaceStickerInSet' + payload = {'user_id': user_id, 'name': name, 'old_sticker': old_sticker, 'sticker': sticker.to_json()} + return await _process_request(token, method_url, params=payload) + async def set_sticker_set_thumbnail(token, name, user_id, thumbnail, format): method_url = r'setStickerSetThumbnail' payload = {'name': name, 'user_id': user_id, 'format': format} From 86833ac38b6206f61dd9ec9e8eb85209704f5374 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:30:03 +0500 Subject: [PATCH 191/480] added birthdates --- telebot/types.py | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 0db7c2159..1d104a098 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -590,6 +590,9 @@ class Chat(JsonDeserializable): Returned only in getChat. :type active_usernames: :obj:`list` of :obj:`str` + :param birthdate: Optional. Birthdate of the other party in a private chat. Returned only in getChat. + :type birthdate: :obj:`str` + :param business_intro: Optional. Business intro for the chat. Returned only in getChat. :type business_intro: :class:`telebot.types.BusinessIntro` @@ -737,6 +740,8 @@ def de_json(cls, json_string): obj['business_opening_hours'] = BusinessOpeningHours.de_json(obj['business_opening_hours']) if 'personal_chat' in obj: obj['personal_chat'] = Chat.de_json(obj['personal_chat']) + if 'birthdate' in obj: + obj['birthdate'] = Birthdate.de_json(obj['birthdate']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -751,7 +756,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, - business_opening_hours=None, personal_chat=None, **kwargs): + business_opening_hours=None, personal_chat=None, birthdate=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -793,6 +798,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.business_location: BusinessLocation = business_location self.business_opening_hours: BusinessOpeningHours = business_opening_hours self.personal_chat: Chat = personal_chat + self.birthdate: Birthdate = birthdate @@ -9682,3 +9688,34 @@ def __init__(self, user_id, first_name=None, last_name=None, username=None, phot self.last_name: Optional[str] = last_name self.username: Optional[str] = username self.photo: Optional[List[PhotoSize]] = photo + + +class Birthdate(JsonDeserializable): + """ + This object represents a user's birthdate. + + Telegram documentation: https://core.telegram.org/bots/api#birthdate + + :param day: Day of the user's birth; 1-31 + :type day: :obj:`int` + + :param month: Month of the user's birth; 1-12 + :type month: :obj:`int` + + :param year: Optional. Year of the user's birth + :type year: :obj:`int` + + :return: Instance of the class + :rtype: :class:`Birthdate` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, day, month, year=None, **kwargs): + self.day: int = day + self.month: int = month + self.year: Optional[int] = year \ No newline at end of file From 2f21c90e6efd5e7fb3d6a990ae9ff280a5cfe3a1 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:36:09 +0500 Subject: [PATCH 192/480] fix f*** tests --- tests/test_handler_backends.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index fa893c489..bb541bf8a 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -71,7 +71,7 @@ def update_type(message): chat_boost_removed = None return types.Update(1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, None, None, None, None) @pytest.fixture() @@ -95,7 +95,7 @@ def reply_to_message_update_type(reply_to_message): chat_boost_removed = None return types.Update(1001234038284, reply_to_message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, - poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed) + poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, None, None, None, None) def next_handler(message): From 027d9d40e0d02d716c4b93661f7b584131124569 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Apr 2024 02:53:10 +0500 Subject: [PATCH 193/480] Fixing dumb issues --- telebot/__init__.py | 6 +++--- telebot/async_telebot.py | 23 ++++++++++++++++++++--- telebot/util.py | 1 + 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 0d6e2aba0..fbd06b440 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -8060,7 +8060,7 @@ def decorator(handler): regexp=regexp, func=func, **kwargs) - self.add_message_handler(handler_dict) + self.add_business_message_handler(handler_dict) return handler return decorator @@ -8151,7 +8151,7 @@ def decorator(handler): regexp=regexp, func=func, **kwargs) - self.add_edited_message_handler(handler_dict) + self.add_edited_business_message_handler(handler_dict) return handler return decorator @@ -8167,7 +8167,7 @@ def add_edited_business_message_handler(self, handler_dict): :param handler_dict: :return: """ - self.edited_message_handlers.append(handler_dict) + self.edited_business_message_handlers.append(handler_dict) def register_edited_business_message_handler(self, callback: Callable, content_types: Optional[List[str]]=None, diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 57ae8e6a4..df46813f5 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -999,6 +999,23 @@ def setup_middleware(self, middleware: BaseMiddleware): self.middlewares.append(middleware) + @staticmethod + def check_commands_input(commands, method_name): + """ + :meta private: + """ + if not isinstance(commands, list) or not all(isinstance(item, str) for item in commands): + logger.error(f"{method_name}: Commands filter should be list of strings (commands), unknown type supplied to the 'commands' filter list. Not able to use the supplied type.") + + + @staticmethod + def check_regexp_input(regexp, method_name): + """ + :meta private: + """ + if not isinstance(regexp, str): + logger.error(f"{method_name}: Regexp filter should be string. Not able to use the supplied type.") + def message_handler(self, commands=None, regexp=None, func=None, content_types=None, chat_types=None, **kwargs): """ Handles ew incoming message of any kind - text, photo, sticker, etc. @@ -2308,7 +2325,7 @@ def decorator(handler): regexp=regexp, func=func, **kwargs) - self.add_message_handler(handler_dict) + self.add_business_message_handler(handler_dict) return handler return decorator @@ -2399,7 +2416,7 @@ def decorator(handler): regexp=regexp, func=func, **kwargs) - self.add_edited_message_handler(handler_dict) + self.add_edited_business_message_handler(handler_dict) return handler return decorator @@ -2415,7 +2432,7 @@ def add_edited_business_message_handler(self, handler_dict): :param handler_dict: :return: """ - self.edited_message_handlers.append(handler_dict) + self.edited_business_message_handlers.append(handler_dict) def register_edited_business_message_handler(self, callback: Callable, content_types: Optional[List[str]]=None, diff --git a/telebot/util.py b/telebot/util.py index 94622fcb7..295c0d1aa 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -48,6 +48,7 @@ "message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member", "chat_join_request", "message_reaction", "message_reaction_count", "chat_boost", "removed_chat_boost", + "business_connection", "business_message", "edited_business_message", "deleted_business_messages" ] From caf3df7a443d51db7f98e9f41c0317f4e6cb5eaa Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Apr 2024 03:11:21 +0500 Subject: [PATCH 194/480] made format optional --- telebot/__init__.py | 15 ++++++++++++--- telebot/async_telebot.py | 14 +++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index fbd06b440..d1432726b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5543,12 +5543,12 @@ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types. ) - def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, thumbnail: Union[Any, str]=None): + def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None, format: Optional[str]=None) -> bool: """ Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. - Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumb + Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumbnail :param name: Sticker set name :type name: :obj:`str` @@ -5556,7 +5556,12 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, thumbn :param user_id: User identifier :type user_id: :obj:`int` - :param thumbnail: A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. + :param thumbnail: A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation + with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), + or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical + requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from + the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via + HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. :type thumbnail: :obj:`filelike object` :param format: Format of the thumbnail, must be one of “static” for a .WEBP or .PNG image, “animated” for a .TGS animation, or “video” for a WEBM video @@ -5565,6 +5570,10 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, thumbn :return: On success, True is returned. :rtype: :obj:`bool` """ + if format is None: + logger.warning("Format in set_sticker_set_thumbnail cannot be None. Setting format to 'static'.") + format = "static" + return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index df46813f5..e2d001659 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6883,12 +6883,12 @@ async def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> return types.UserChatBoosts.de_json(result) - async def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, thumbnail: Union[Any, str]=None): + async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None, format: Optional[str]=None) -> bool: """ Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. - Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumb + Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumbnail :param name: Sticker set name :type name: :obj:`str` @@ -6896,12 +6896,20 @@ async def set_sticker_set_thumbnail(self, name: str, user_id: int, format: str, :param user_id: User identifier :type user_id: :obj:`int` - :param thumbnail: A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. + :param thumbnail: A .WEBP or .PNG image with the thumbnail, must be up to 128 kilobytes in size and have a width and height of exactly 100px, or a .TGS animation + with a thumbnail up to 32 kilobytes in size (see https://core.telegram.org/stickers#animated-sticker-requirements for animated sticker technical requirements), + or a WEBM video with the thumbnail up to 32 kilobytes in size; see https://core.telegram.org/stickers#video-sticker-requirements for video sticker technical + requirements. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from + the Internet, or upload a new one using multipart/form-data. More information on Sending Files ». Animated and video sticker set thumbnails can't be uploaded via + HTTP URL. If omitted, then the thumbnail is dropped and the first sticker is used as the thumbnail. :type thumbnail: :obj:`filelike object` :return: On success, True is returned. :rtype: :obj:`bool` """ + if format is None: + logger.warning("Format in set_sticker_set_thumbnail cannot be None. Setting format to 'static'.") + format = "static" return await asyncio_helper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") From 325da2fa0fc0cb6f845aafdfba956d44c76797c2 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 5 Apr 2024 03:37:37 +0500 Subject: [PATCH 195/480] Added all_states for StatesGroup (#2215) * Update asyncio_handler_backends.py * Update handler_backends.py * Update handler_backends.py * Update asyncio_handler_backends.py --- telebot/asyncio_handler_backends.py | 2 +- telebot/handler_backends.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/asyncio_handler_backends.py b/telebot/asyncio_handler_backends.py index a565023fc..0861a9893 100644 --- a/telebot/asyncio_handler_backends.py +++ b/telebot/asyncio_handler_backends.py @@ -83,7 +83,7 @@ def __init_subclass__(cls) -> None: state_list.append(value) cls._state_list = state_list - @property + @classmethod def state_list(self): return self._state_list diff --git a/telebot/handler_backends.py b/telebot/handler_backends.py index 2e4f86eab..b95861e0b 100644 --- a/telebot/handler_backends.py +++ b/telebot/handler_backends.py @@ -194,7 +194,7 @@ def __init_subclass__(cls) -> None: state_list.append(value) cls._state_list = state_list - @property + @classmethod def state_list(self): return self._state_list From 2ee6c7f3fdc2109f335da9b48a621fde5a82b631 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 5 Apr 2024 15:38:40 +0300 Subject: [PATCH 196/480] Bot API 7.2 u1 - Removed the fields is_animated and is_video from the class [StickerSet](https://core.telegram.org/bots/api#stickerset). - Removed the parameter sticker_format from the method [createNewStickerSet](https://core.telegram.org/bots/api#createnewstickerset). --- telebot/__init__.py | 23 +++++++++++++++++------ telebot/apihelper.py | 12 ++++++------ telebot/async_telebot.py | 11 ++++++----- telebot/asyncio_helper.py | 15 ++++++++------- telebot/types.py | 23 ++++++++++++++++------- 5 files changed, 53 insertions(+), 31 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d1432726b..4c3040d84 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -213,6 +213,7 @@ def __init__( # handlers self.exception_handler = exception_handler self.update_listener = [] + self.message_handlers = [] self.edited_message_handlers = [] self.channel_post_handlers = [] @@ -247,6 +248,8 @@ def __init__( 'edited_message': [], 'channel_post': [], 'edited_channel_post': [], + 'message_reaction': [], + 'message_reaction_count': [], 'inline_query': [], 'chosen_inline_result': [], 'callback_query': [], @@ -256,7 +259,13 @@ def __init__( 'poll_answer': [], 'my_chat_member': [], 'chat_member': [], - 'chat_join_request': [] + 'chat_join_request': [], + 'chat_boost': [], + 'removed_chat_boost': [], + 'business_connection': [], + 'business_message': [], + 'edited_business_message': [], + 'deleted_business_messages': [], } self.default_middleware_handlers = [] if apihelper.ENABLE_MIDDLEWARE and use_class_middlewares: @@ -5570,8 +5579,8 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[An :return: On success, True is returned. :rtype: :obj:`bool` """ - if format is None: - logger.warning("Format in set_sticker_set_thumbnail cannot be None. Setting format to 'static'.") + if not format: + logger.warning("Deprecation warning. 'format' parameter is required in set_sticker_set_thumbnail. Setting format to 'static'.") format = "static" return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) @@ -5856,7 +5865,7 @@ def create_new_sticker_set( :param stickers: List of stickers to be added to the set :type stickers: :obj:`list` of :class:`telebot.types.InputSticker` - :param sticker_format: Format of stickers in the set, must be one of “static”, “animated”, “video” + :param sticker_format: deprecated :type sticker_format: :obj:`str` :return: On success, True is returned. @@ -5880,9 +5889,11 @@ def create_new_sticker_set( raise ValueError('You must pass at least one sticker') stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] + if sticker_format: + logger.warning('The parameter "sticker_format" is deprecated.') + return apihelper.create_new_sticker_set( - self.token, user_id, name, title, stickers, sticker_format, sticker_type=sticker_type, - needs_repainting=needs_repainting) + self.token, user_id, name, title, stickers, sticker_type=sticker_type, needs_repainting=needs_repainting) def add_sticker_to_set( diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 1b3a6df99..3f537065c 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1708,23 +1708,26 @@ def set_sticker_set_title(token, name, title): payload = {'name': name, 'title': title} return _make_request(token, method_url, params=payload, method='post') + def delete_sticker_set(token, name): method_url = 'deleteStickerSet' payload = {'name': name} return _make_request(token, method_url, params=payload, method='post') + def set_sticker_emoji_list(token, sticker, emoji_list): method_url = 'setStickerEmojiList' payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)} return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( - token, user_id, name, title, stickers, sticker_format, sticker_type=None, needs_repainting=None): + token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' - payload = {'user_id': user_id, 'name': name, 'title': title, 'sticker_format': sticker_format} + payload = {'user_id': user_id, 'name': name, 'title': title} if sticker_type: payload['sticker_type'] = sticker_type - if needs_repainting: + if needs_repainting is not None: payload['needs_repainting'] = needs_repainting files = {} @@ -1741,8 +1744,6 @@ def create_new_sticker_set( payload['stickers'] = json.dumps(lst) - - return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1750,7 +1751,6 @@ def add_sticker_to_set(token, user_id, name, sticker): method_url = 'addStickerToSet' json_dict, files = sticker.convert_input_sticker() payload = {'user_id': user_id, 'name': name, 'sticker': json_dict} - return _make_request(token, method_url, params=payload, files=files, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index e2d001659..daeb55d5c 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6907,8 +6907,8 @@ async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Un :return: On success, True is returned. :rtype: :obj:`bool` """ - if format is None: - logger.warning("Format in set_sticker_set_thumbnail cannot be None. Setting format to 'static'.") + if not format: + logger.warning("Deprecation warning. 'format' parameter is required in set_sticker_set_thumbnail. Setting format to 'static'.") format = "static" return await asyncio_helper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) @@ -7184,7 +7184,7 @@ async def create_new_sticker_set( :param stickers: List of stickers to be added to the set :type stickers: :obj:`list` of :class:`telebot.types.InputSticker` - :param sticker_format: Format of stickers in the set, must be one of “static”, “animated”, “video” + :param sticker_format: deprecated :type sticker_format: :obj:`str` :return: On success, True is returned. @@ -7208,10 +7208,11 @@ async def create_new_sticker_set( raise ValueError('You must pass at least one sticker') stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] + if sticker_format: + logger.warning('The parameter "sticker_format" is deprecated.') - return await asyncio_helper.create_new_sticker_set( - self.token, user_id, name, title, stickers, sticker_format, sticker_type, needs_repainting) + self.token, user_id, name, title, stickers, sticker_type, needs_repainting) async def add_sticker_to_set( diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index e1fcdec36..3aadccc65 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1481,7 +1481,7 @@ async def send_invoice( send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None,reply_parameters=None): + protect_content=None, message_thread_id=None, reply_parameters=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1513,6 +1513,7 @@ async def send_invoice( At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount. :param protect_content: Protects the contents of the sent message from forwarding and saving :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + :param reply_parameters: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. :return: """ method_url = r'sendInvoice' @@ -1648,7 +1649,7 @@ async def answer_inline_query(token, inline_query_id, results, cache_time=None, payload['next_offset'] = next_offset if button is not None: payload["button"] = button.to_json() - + return await _process_request(token, method_url, params=payload, method='post') @@ -1706,12 +1707,12 @@ async def set_sticker_set_title(token, name, title): return await _process_request(token, method_url, params=payload, method='post') async def create_new_sticker_set( - token, user_id, name, title, stickers, sticker_format, sticker_type=None, needs_repainting=None): + token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' - payload = {'user_id': user_id, 'name': name, 'title': title, 'sticker_format': sticker_format} + payload = {'user_id': user_id, 'name': name, 'title': title} if sticker_type: payload['sticker_type'] = sticker_type - if needs_repainting: + if needs_repainting is not None: payload['needs_repainting'] = needs_repainting files = {} @@ -1728,7 +1729,7 @@ async def create_new_sticker_set( payload['stickers'] = json.dumps(lst) - + return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1736,7 +1737,7 @@ async def add_sticker_to_set(token, user_id, name, sticker): method_url = 'addStickerToSet' json_dict, files = sticker.convert_input_sticker() payload = {'user_id': user_id, 'name': name, 'sticker': json_dict} - + return await _process_request(token, method_url, params=payload, files=files, method='post') diff --git a/telebot/types.py b/telebot/types.py index 1d104a098..9e3af63ec 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -900,7 +900,6 @@ class Message(JsonDeserializable): :type forward_from_chat: :class:`telebot.types.Chat` :param forward_from_message_id: deprecated. - message in the channel :type forward_from_message_id: :obj:`int` :param forward_signature: deprecated. @@ -6396,10 +6395,10 @@ class StickerSet(JsonDeserializable): :param sticker_type: Type of stickers in the set, currently one of “regular”, “mask”, “custom_emoji” :type sticker_type: :obj:`str` - :param is_animated: True, if the sticker set contains animated stickers + :param is_animated: deprecated :type is_animated: :obj:`bool` - :param is_video: True, if the sticker set contains video stickers + :param is_video: deprecated :type is_video: :obj:`bool` :param contains_masks: deprecated @@ -6428,15 +6427,20 @@ def de_json(cls, json_string): obj['thumbnail'] = None return cls(**obj) - def __init__(self, name, title, sticker_type, is_animated, is_video, stickers, thumbnail=None, **kwargs): + def __init__(self, name, title, sticker_type, is_animated=None, is_video=None, stickers=None, thumbnail=None, **kwargs): self.name: str = name self.title: str = title self.sticker_type: str = sticker_type - self.is_animated: bool = is_animated - self.is_video: bool = is_video self.stickers: List[Sticker] = stickers self.thumbnail: PhotoSize = thumbnail + if is_animated is not None: + logger.warning('The parameter "is_animated" is deprecated.') + if is_video is not None: + logger.warning('The parameter "is_video" is deprecated.') + if stickers is None: + raise ValueError('The parameter "stickers" is required for StickerSet.') + @property def thumb(self): logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') @@ -8033,13 +8037,18 @@ class InputSticker(Dictionaryable, JsonSerializable): :rtype: :class:`telebot.types.InputSticker` """ - def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], format: str, mask_position: Optional[MaskPosition]=None, keywords: Optional[List[str]]=None) -> None: + def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], format: Optional[str]=None, + mask_position: Optional[MaskPosition]=None, keywords: Optional[List[str]]=None) -> None: self.sticker: Union[str, InputFile] = sticker self.emoji_list: List[str] = emoji_list self.mask_position: Optional[MaskPosition] = mask_position self.keywords: Optional[List[str]] = keywords self.format: str = format + if not self.format: + logger.warning("Deprecation warning. 'format' parameter is required in InputSticker. Setting format to 'static'.") + self.format = "static" + if service_utils.is_string(self.sticker): self._sticker_name = '' self._sticker_dic = self.sticker From 96c9768d0a2554dafd98b09e3b70e2455a20aded Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 5 Apr 2024 18:56:09 +0300 Subject: [PATCH 197/480] Update telebot/__init__.py Co-authored-by: _run --- telebot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4c3040d84..0dde90f1b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5890,7 +5890,7 @@ def create_new_sticker_set( stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] if sticker_format: - logger.warning('The parameter "sticker_format" is deprecated.') + logger.warning('The parameter "sticker_format" is deprecated since Bot API 7.2+. Stickers can now be mixed') return apihelper.create_new_sticker_set( self.token, user_id, name, title, stickers, sticker_type=sticker_type, needs_repainting=needs_repainting) From 1d6d60fef85fa708bf0b4fffbe430c5bf507b463 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 5 Apr 2024 21:56:14 +0300 Subject: [PATCH 198/480] Update StickerSet to new signature. --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- telebot/types.py | 34 +++++++++++++++++----------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 0dde90f1b..823324359 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5890,7 +5890,7 @@ def create_new_sticker_set( stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] if sticker_format: - logger.warning('The parameter "sticker_format" is deprecated since Bot API 7.2+. Stickers can now be mixed') + logger.warning('The parameter "sticker_format" is deprecated since Bot API 7.2. Stickers can now be mixed') return apihelper.create_new_sticker_set( self.token, user_id, name, title, stickers, sticker_type=sticker_type, needs_repainting=needs_repainting) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index daeb55d5c..d24a025dd 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7209,7 +7209,7 @@ async def create_new_sticker_set( stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] if sticker_format: - logger.warning('The parameter "sticker_format" is deprecated.') + logger.warning('The parameter "sticker_format" is deprecated since Bot API 7.2. Stickers can now be mixed') return await asyncio_helper.create_new_sticker_set( self.token, user_id, name, title, stickers, sticker_type, needs_repainting) diff --git a/telebot/types.py b/telebot/types.py index 9e3af63ec..f05df3cad 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6395,15 +6395,6 @@ class StickerSet(JsonDeserializable): :param sticker_type: Type of stickers in the set, currently one of “regular”, “mask”, “custom_emoji” :type sticker_type: :obj:`str` - :param is_animated: deprecated - :type is_animated: :obj:`bool` - - :param is_video: deprecated - :type is_video: :obj:`bool` - - :param contains_masks: deprecated - :type contains_masks: :obj:`bool` - :param stickers: List of all set stickers :type stickers: :obj:`list` of :class:`telebot.types.Sticker` @@ -6427,20 +6418,13 @@ def de_json(cls, json_string): obj['thumbnail'] = None return cls(**obj) - def __init__(self, name, title, sticker_type, is_animated=None, is_video=None, stickers=None, thumbnail=None, **kwargs): + def __init__(self, name, title, sticker_type, stickers, thumbnail=None, **kwargs): self.name: str = name self.title: str = title self.sticker_type: str = sticker_type self.stickers: List[Sticker] = stickers self.thumbnail: PhotoSize = thumbnail - if is_animated is not None: - logger.warning('The parameter "is_animated" is deprecated.') - if is_video is not None: - logger.warning('The parameter "is_video" is deprecated.') - if stickers is None: - raise ValueError('The parameter "stickers" is required for StickerSet.') - @property def thumb(self): logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') @@ -6454,6 +6438,22 @@ def contains_masks(self): logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type instead"') return self.sticker_type == 'mask' + @property + def is_animated(self): + """ + Deprecated since Bot API 7.2. Stickers can be mixed now. + """ + logger.warning('The parameter "is_animated" is deprecated since Bot API 7.2. Stickers can now be mixed') + return False + + @property + def is_video(self): + """ + Deprecated since Bot API 7.2. Stickers can be mixed now. + """ + logger.warning('The parameter "is_video" is deprecated since Bot API 7.2. Stickers can now be mixed') + return False + class Sticker(JsonDeserializable): """ From 9cb808a02230bf72c0bbbea084909f1351fdd305 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 5 Apr 2024 22:00:44 +0300 Subject: [PATCH 199/480] Clear old deprecated fields. --- telebot/types.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index f05df3cad..ecedf69f2 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -893,24 +893,6 @@ class Message(JsonDeserializable): :param chat: Conversation the message belongs to :type chat: :class:`telebot.types.Chat` - :param forward_from: deprecated. - :type forward_from: :class:`telebot.types.User` - - :param forward_from_chat: deprecated. - :type forward_from_chat: :class:`telebot.types.Chat` - - :param forward_from_message_id: deprecated. - :type forward_from_message_id: :obj:`int` - - :param forward_signature: deprecated. - :type forward_signature: :obj:`str` - - :param forward_sender_name: deprecated. - :type forward_sender_name: :obj:`str` - - :param forward_date: deprecated. - :type forward_date: :obj:`int` - :forward_origin: Optional. For forwarded messages, information about the original message; :type forward_origin: :class:`telebot.types.MessageOrigin` From e8074eb2747628189a1c06fd428b1643a4115e10 Mon Sep 17 00:00:00 2001 From: Artem Lavrenov Date: Sat, 6 Apr 2024 16:47:40 +0300 Subject: [PATCH 200/480] Example bot using message reactions (emoji) --- .../message_reaction_example.py | 35 +++++++++++++++++++ examples/message_reaction_example.py | 33 +++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 examples/asynchronous_telebot/message_reaction_example.py create mode 100644 examples/message_reaction_example.py diff --git a/examples/asynchronous_telebot/message_reaction_example.py b/examples/asynchronous_telebot/message_reaction_example.py new file mode 100644 index 000000000..a3e078f60 --- /dev/null +++ b/examples/asynchronous_telebot/message_reaction_example.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 + +# This is a simple bot using message reactions (emoji) +# https://core.telegram.org/bots/api#reactiontype +# https://core.telegram.org/bots/api#update +# allowed_updates: Specify an empty list to receive all update types except, chat_member, message_reaction, and message_reaction_count. +# If you want to receive message_reaction events, you cannot simply leave the allowed_updates=None default value. +# The default list of events does not include chat_member, message_reaction, and message_reaction_count events. +# You must explicitly specify all the events you wish to receive and add message_reaction to this list. +# It’s also important to note that after using allowed_updates=[...], in the future, using allowed_updates=None will mean +# that the list of events you will receive will consist of the events you last explicitly specified. + +import random +from telebot.async_telebot import AsyncTeleBot +from telebot.types import ReactionTypeEmoji + +API_TOKEN = '' +bot = AsyncTeleBot(API_TOKEN) + + + +# Send a reactions to all messages with content_type 'text' (content_types defaults to ['text']) +@bot.message_handler(func=lambda message: True) +async def send_reaction(message): + emo = ["\U0001F525", "\U0001F917", "\U0001F60E"] # or use ["🔥", "🤗", "😎"] + await bot.set_message_reaction(message.chat.id, message.id, [ReactionTypeEmoji(random.choice(emo))], is_big=False) + + +@bot.message_reaction_handler(func=lambda message: True) +async def get_reactions(message): + await bot.reply_to(message, f"You changed the reaction from {[r.emoji for r in message.old_reaction]} to {[r.emoji for r in message.new_reaction]}") + + +import asyncio +asyncio.run(bot.infinity_polling(allowed_updates=['message', 'message_reaction'])) diff --git a/examples/message_reaction_example.py b/examples/message_reaction_example.py new file mode 100644 index 000000000..65178d25a --- /dev/null +++ b/examples/message_reaction_example.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 + +# This is a simple bot using message reactions (emoji) +# https://core.telegram.org/bots/api#reactiontype +# https://core.telegram.org/bots/api#update +# allowed_updates: Specify an empty list to receive all update types except, chat_member, message_reaction, and message_reaction_count. +# If you want to receive message_reaction events, you cannot simply leave the allowed_updates=None default value. +# The default list of events does not include chat_member, message_reaction, and message_reaction_count events. +# You must explicitly specify all the events you wish to receive and add message_reaction to this list. +# It’s also important to note that after using allowed_updates=[...], in the future, using allowed_updates=None will mean +# that the list of events you will receive will consist of the events you last explicitly specified. + +import random +import telebot +from telebot.types import ReactionTypeEmoji + +API_TOKEN = '' +bot = telebot.TeleBot(API_TOKEN) + + +# Send a reactions to all messages with content_type 'text' (content_types defaults to ['text']) +@bot.message_handler(func=lambda message: True) +def send_reaction(message): + emo = ["\U0001F525", "\U0001F917", "\U0001F60E"] # or use ["🔥", "🤗", "😎"] + bot.set_message_reaction(message.chat.id, message.id, [ReactionTypeEmoji(random.choice(emo))], is_big=False) + + +@bot.message_reaction_handler(func=lambda message: True) +def get_reactions(message): + bot.reply_to(message, f"You changed the reaction from {[r.emoji for r in message.old_reaction]} to {[r.emoji for r in message.new_reaction]}") + + +bot.infinity_polling(allowed_updates=['message', 'message_reaction']) From d075596d07822e848a053ad8b73eae8b9d6a0e07 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Tue, 9 Apr 2024 10:51:20 +0300 Subject: [PATCH 201/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index c9edf448c..423df2324 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'coder2020official' # The full version, including alpha/beta/rc tags -release = '4.16.1' +release = '4.17.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 68f0254ea..fde7a8685 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.16.1" +version = "4.17.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 0b4b31ee0..3eb8b787f 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.16.1' +__version__ = '4.17.0' From 04e815cd91a9eca721984aa65e8f85476f24b34a Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Wed, 10 Apr 2024 21:01:17 +0400 Subject: [PATCH 202/480] added method html_text in TextQuote --- telebot/types.py | 104 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_types.py | 4 +- 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 498e1097c..b1630fd1b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8988,6 +8988,110 @@ def __init__(self, text: str, position: int, self.position: Optional[int] = position self.is_manual: Optional[bool] = is_manual + def __html_text(self, text, entities): + """ + Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" + + .. code-block:: python3 + :caption: Example: + + message.quote.html_text + >> "Test parse formatting, url, text_mention and mention @username" + + Custom subs: + You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. + .. code-block:: python3 + :caption: Example: + + message.custom_subs = {"bold": "{text}", "italic": "{text}", "mention": "{text}"} + message.html_text + >> "Test parse formatting, url and text_mention and mention @username" + """ + + if not entities: + return text.replace("&", "&").replace("<", "<").replace(">", ">") + + _subs = { + "bold": "{text}", + "italic": "{text}", + "pre": "
{text}
", + "code": "{text}", + "text_link": "{text}", + "strikethrough": "{text}", + "underline": "{text}", + "spoiler": "{text}", + "custom_emoji": "{text}", + "blockquote": "
{text}
", + } + + if hasattr(self, "custom_subs"): + for key, value in self.custom_subs.items(): + _subs[key] = value + utf16_text = text.encode("utf-16-le") + html_text = "" + + def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): + upd_text = upd_text.decode("utf-16-le") + if subst_type == "text_mention": + subst_type = "text_link" + url = "tg://user?id={0}".format(user.id) + elif subst_type == "mention": + url = "https://t.me/{0}".format(upd_text[1:]) + upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") + if not subst_type or not _subs.get(subst_type): + return upd_text + subs = _subs.get(subst_type) + if subst_type == "custom_emoji": + return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) + return subs.format(text=upd_text, url=url) + + offset = 0 + start_index = 0 + end_index = 0 + for entity in entities: + if entity.offset > offset: + # when the offset is not 0: for example, a __b__ + # we need to add the text before the entity to the html_text + html_text += func(utf16_text[offset * 2: entity.offset * 2]) + offset = entity.offset + + new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + offset += entity.length + end_index = len(html_text) + elif entity.offset == offset: + new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + end_index = len(html_text) + offset += entity.length + else: + # Here we are processing nested entities. + # We shouldn't update offset, because they are the same as entity before. + # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, + # And we don't change it). + entity_string = html_text[start_index: end_index].encode("utf-16-le") + formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, + custom_emoji_id=entity.custom_emoji_id). \ + replace("&", "&").replace("<", "<").replace(">", ">") + html_text = html_text[:start_index] + formatted_string + html_text[end_index:] + end_index = len(html_text) + + if offset * 2 < len(utf16_text): + html_text += func(utf16_text[offset * 2:]) + + return html_text + + @property + def html_text(self): + """ + Returns html-rendered text. + """ + return self.__html_text(self.text, self.entities) + class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable): """ diff --git a/tests/test_types.py b/tests/test_types.py index 06bcae1ee..197834748 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -306,6 +306,8 @@ def test_message_entity(): assert message_6.html_text == "<b>b</b> <i>i</i>" - + sample_string_7 = r'{"update_id":934522167,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"reply_to_message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en"},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1712765863,"text":"text @UserName b i s u c p #hashtag https://example.com","entities":[{"offset":5,"length":9,"type":"mention"},{"offset":15,"length":1,"type":"bold"},{"offset":17,"length":1,"type":"italic"},{"offset":19,"length":1,"type":"strikethrough"},{"offset":21,"length":1,"type":"underline"},{"offset":23,"length":1,"type":"code"},{"offset":25,"length":1,"type":"spoiler"},{"offset":27,"length":8,"type":"hashtag"},{"offset":36,"length":19,"type":"url"}],"link_preview_options":{"is_disabled":true}},"quote":{"text":"text @UserName b i s u c p #hashtag https://example.com","entities":[{"offset":15,"length":1,"type":"bold"},{"offset":17,"length":1,"type":"italic"},{"offset":19,"length":1,"type":"strikethrough"},{"offset":21,"length":1,"type":"underline"},{"offset":25,"length":1,"type":"spoiler"}],"position":0,"is_manual":true},"text":"quote reply"}}' + message_7 = types.Update.de_json(sample_string_7).message + assert message_7.quote.html_text == 'text @UserName b i s u c p #hashtag https://example.com' From e7d3b979fd01edca513d4ea31aaecc4a5b67361a Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Fri, 12 Apr 2024 21:31:38 +0400 Subject: [PATCH 203/480] Renamed telebot.types.Message.__html_text to apply_html_entities and moved it to telebot/formatting --- telebot/formatting.py | 111 +++++++++++++++++++++-- telebot/types.py | 203 ++---------------------------------------- 2 files changed, 111 insertions(+), 203 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index c0f442013..3ececdd65 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -4,11 +4,9 @@ .. versionadded:: 4.5.1 """ -import html - import re - -from typing import Optional +import html +from typing import Optional, List def format_text(*args, separator="\n"): @@ -34,7 +32,6 @@ def format_text(*args, separator="\n"): return separator.join(args) - def escape_html(content: str) -> str: """ Escapes HTML characters in a string of HTML. @@ -66,6 +63,110 @@ def escape_markdown(content: str) -> str: return reparse +def apply_html_entities(text: str, entities: Optional[List], custom_subs: Optional[dict[str, str]]) -> str: + """ + Author: @sviat9440 + Updaters: @badiboy, @EgorKhabarov + Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" + + .. code-block:: python3 + :caption: Example: + + apply_html_entities(text, entities) + >> "Test parse formatting, url, text_mention and mention @username" + + Custom subs: + You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. + .. code-block:: python3 + :caption: Example: + + apply_html_entities( + text, + entities, + {"bold": "{text}", "italic": "{text}", "mention": "{text}"}, + ) + >> "Test parse formatting, url and text_mention and mention @username" + """ + + if not entities: + return text.replace("&", "&").replace("<", "<").replace(">", ">") + + _subs = { + "bold": "{text}", + "italic": "{text}", + "pre": "
{text}
", + "code": "{text}", + # "url": "{text}", # @badiboy plain URLs have no text and do not need tags + "text_link": "{text}", + "strikethrough": "{text}", + "underline": "{text}", + "spoiler": "{text}", + "custom_emoji": "{text}", + "blockquote": "
{text}
", + } + + if custom_subs: + for key, value in custom_subs.items(): + _subs[key] = value + utf16_text = text.encode("utf-16-le") + html_text = "" + + def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): + upd_text = upd_text.decode("utf-16-le") + if subst_type == "text_mention": + subst_type = "text_link" + url = "tg://user?id={0}".format(user.id) + elif subst_type == "mention": + url = "https://t.me/{0}".format(upd_text[1:]) + upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") + if not subst_type or not _subs.get(subst_type): + return upd_text + subs = _subs.get(subst_type) + if subst_type == "custom_emoji": + return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) + return subs.format(text=upd_text, url=url) + + offset = 0 + start_index = 0 + end_index = 0 + for entity in entities: + if entity.offset > offset: + # when the offset is not 0: for example, a __b__ + # we need to add the text before the entity to the html_text + html_text += func(utf16_text[offset * 2: entity.offset * 2]) + offset = entity.offset + + new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + offset += entity.length + end_index = len(html_text) + elif entity.offset == offset: + new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + end_index = len(html_text) + offset += entity.length + else: + # Here we are processing nested entities. + # We shouldn't update offset, because they are the same as entity before. + # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, + # And we don't change it). + entity_string = html_text[start_index: end_index].encode("utf-16-le") + formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, + custom_emoji_id=entity.custom_emoji_id). \ + replace("&", "&").replace("<", "<").replace(">", ">") + html_text = html_text[:start_index] + formatted_string + html_text[end_index:] + end_index = len(html_text) + + if offset * 2 < len(utf16_text): + html_text += func(utf16_text[offset * 2:]) + + return html_text + + def mbold(content: str, escape: Optional[bool]=True) -> str: """ Returns a Markdown-formatted bold string. diff --git a/telebot/types.py b/telebot/types.py index b1630fd1b..7c2782788 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -14,6 +14,8 @@ import json from telebot import service_utils +from telebot.formatting import apply_html_entities + DISABLE_KEYLEN_ERROR = False @@ -1474,117 +1476,19 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso setattr(self, key, options[key]) self.json = json_string - - def __html_text(self, text, entities): - """ - Author: @sviat9440 - Updaters: @badiboy, @EgorKhabarov - Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" - - .. code-block:: python3 - :caption: Example: - - message.html_text - >> "Test parse formatting, url, text_mention and mention @username" - - Custom subs: - You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. - .. code-block:: python3 - :caption: Example: - - message.custom_subs = {"bold": "{text}", "italic": "{text}", "mention": "{text}"} - message.html_text - >> "Test parse formatting, url and text_mention and mention @username" - """ - - if not entities: - return text.replace("&", "&").replace("<", "<").replace(">", ">") - - _subs = { - "bold": "{text}", - "italic": "{text}", - "pre": "
{text}
", - "code": "{text}", - # "url": "{text}", # @badiboy plain URLs have no text and do not need tags - "text_link": "{text}", - "strikethrough": "{text}", - "underline": "{text}", - "spoiler": "{text}", - "custom_emoji": "{text}", - "blockquote": "
{text}
", - } - - if hasattr(self, "custom_subs"): - for key, value in self.custom_subs.items(): - _subs[key] = value - utf16_text = text.encode("utf-16-le") - html_text = "" - - def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): - upd_text = upd_text.decode("utf-16-le") - if subst_type == "text_mention": - subst_type = "text_link" - url = "tg://user?id={0}".format(user.id) - elif subst_type == "mention": - url = "https://t.me/{0}".format(upd_text[1:]) - upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") - if not subst_type or not _subs.get(subst_type): - return upd_text - subs = _subs.get(subst_type) - if subst_type == "custom_emoji": - return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) - return subs.format(text=upd_text, url=url) - - offset = 0 - start_index = 0 - end_index = 0 - for entity in entities: - if entity.offset > offset: - # when the offset is not 0: for example, a __b__ - # we need to add the text before the entity to the html_text - html_text += func(utf16_text[offset * 2 : entity.offset * 2]) - offset = entity.offset - - new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], subst_type=entity.type, url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) - start_index = len(html_text) - html_text += new_string - offset += entity.length - end_index = len(html_text) - elif entity.offset == offset: - new_string = func(utf16_text[offset * 2 : (offset + entity.length) * 2], subst_type=entity.type, url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) - start_index = len(html_text) - html_text += new_string - end_index = len(html_text) - offset += entity.length - else: - # Here we are processing nested entities. - # We shouldn't update offset, because they are the same as entity before. - # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, - # And we don't change it). - entity_string = html_text[start_index : end_index].encode("utf-16-le") - formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id).\ - replace("&", "&").replace("<", "<").replace(">",">") - html_text = html_text[:start_index] + formatted_string + html_text[end_index:] - end_index = len(html_text) - - if offset * 2 < len(utf16_text): - html_text += func(utf16_text[offset * 2:]) - - return html_text - @property def html_text(self): """ Returns html-rendered text. """ - return self.__html_text(self.text, self.entities) + return apply_html_entities(self.text, self.entities, getattr(self, "custom_subs", None)) @property def html_caption(self): """ Returns html-rendered caption. """ - return self.__html_text(self.caption, self.caption_entities) + return apply_html_entities(self.caption, self.caption_entities, getattr(self, "custom_subs", None)) @property def voice_chat_scheduled(self): @@ -8988,109 +8892,12 @@ def __init__(self, text: str, position: int, self.position: Optional[int] = position self.is_manual: Optional[bool] = is_manual - def __html_text(self, text, entities): - """ - Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" - - .. code-block:: python3 - :caption: Example: - - message.quote.html_text - >> "Test parse formatting, url, text_mention and mention @username" - - Custom subs: - You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. - .. code-block:: python3 - :caption: Example: - - message.custom_subs = {"bold": "{text}", "italic": "{text}", "mention": "{text}"} - message.html_text - >> "Test parse formatting, url and text_mention and mention @username" - """ - - if not entities: - return text.replace("&", "&").replace("<", "<").replace(">", ">") - - _subs = { - "bold": "{text}", - "italic": "{text}", - "pre": "
{text}
", - "code": "{text}", - "text_link": "{text}", - "strikethrough": "{text}", - "underline": "{text}", - "spoiler": "{text}", - "custom_emoji": "{text}", - "blockquote": "
{text}
", - } - - if hasattr(self, "custom_subs"): - for key, value in self.custom_subs.items(): - _subs[key] = value - utf16_text = text.encode("utf-16-le") - html_text = "" - - def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): - upd_text = upd_text.decode("utf-16-le") - if subst_type == "text_mention": - subst_type = "text_link" - url = "tg://user?id={0}".format(user.id) - elif subst_type == "mention": - url = "https://t.me/{0}".format(upd_text[1:]) - upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") - if not subst_type or not _subs.get(subst_type): - return upd_text - subs = _subs.get(subst_type) - if subst_type == "custom_emoji": - return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) - return subs.format(text=upd_text, url=url) - - offset = 0 - start_index = 0 - end_index = 0 - for entity in entities: - if entity.offset > offset: - # when the offset is not 0: for example, a __b__ - # we need to add the text before the entity to the html_text - html_text += func(utf16_text[offset * 2: entity.offset * 2]) - offset = entity.offset - - new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, - url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) - start_index = len(html_text) - html_text += new_string - offset += entity.length - end_index = len(html_text) - elif entity.offset == offset: - new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, - url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) - start_index = len(html_text) - html_text += new_string - end_index = len(html_text) - offset += entity.length - else: - # Here we are processing nested entities. - # We shouldn't update offset, because they are the same as entity before. - # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, - # And we don't change it). - entity_string = html_text[start_index: end_index].encode("utf-16-le") - formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, - custom_emoji_id=entity.custom_emoji_id). \ - replace("&", "&").replace("<", "<").replace(">", ">") - html_text = html_text[:start_index] + formatted_string + html_text[end_index:] - end_index = len(html_text) - - if offset * 2 < len(utf16_text): - html_text += func(utf16_text[offset * 2:]) - - return html_text - @property def html_text(self): """ Returns html-rendered text. """ - return self.__html_text(self.text, self.entities) + return apply_html_entities(self.text, self.entities, getattr(self, "custom_subs", None)) class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable): From 870f5e190e26155c68bb8d96e87cdc87995d448f Mon Sep 17 00:00:00 2001 From: qeez Date: Fri, 12 Apr 2024 22:09:00 +0300 Subject: [PATCH 204/480] Fix grammar error --- telebot/async_telebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d24a025dd..d023568f8 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -1018,7 +1018,7 @@ def check_regexp_input(regexp, method_name): def message_handler(self, commands=None, regexp=None, func=None, content_types=None, chat_types=None, **kwargs): """ - Handles ew incoming message of any kind - text, photo, sticker, etc. + Handles new incoming message of any kind - text, photo, sticker, etc. As a parameter to the decorator function, it passes :class:`telebot.types.Message` object. All message handlers are tested in the order they were added. From ebb9a7ff13fa5d5132f79905820648730721c4c8 Mon Sep 17 00:00:00 2001 From: chiri <109767616+chiri1488@users.noreply.github.com> Date: Wed, 17 Apr 2024 10:57:49 +0300 Subject: [PATCH 205/480] update: copyright date updating the copyright date from 2023 to 2024 --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 423df2324..f0502dfa6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,7 +18,7 @@ # -- Project information ----------------------------------------------------- project = 'pyTelegramBotAPI Documentation' -copyright = '2022-2023, coder2020official' +copyright = '2022-2024, coder2020official' author = 'coder2020official' # The full version, including alpha/beta/rc tags From 01e921e7ccce5e62b91a8703eeac9a305c1f02e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:36:11 +0000 Subject: [PATCH 206/480] Bump aiohttp from 3.9.0 to 3.9.4 Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.0 to 3.9.4. - [Release notes](https://github.com/aio-libs/aiohttp/releases) - [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst) - [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.0...v3.9.4) --- updated-dependencies: - dependency-name: aiohttp dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 049b84f84..32cb38aa1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest requests==2.31.0 wheel==0.38.1 -aiohttp==3.9.0 +aiohttp==3.9.4 From dc82acc6bcac72ecdf2428109b102fd2346b13ce Mon Sep 17 00:00:00 2001 From: chiri <109767616+chirizxc@users.noreply.github.com> Date: Fri, 19 Apr 2024 10:22:56 +0300 Subject: [PATCH 207/480] automatic updates of copyright year in lib --- docs/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f0502dfa6..f2ab5ac09 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,12 +13,12 @@ # import os # import sys # sys.path.insert(0, os.path.abspath('.')) - +from datetime import datetime # -- Project information ----------------------------------------------------- project = 'pyTelegramBotAPI Documentation' -copyright = '2022-2024, coder2020official' +copyright = f'2022-{datetime.now().year}, coder2020official' author = 'coder2020official' # The full version, including alpha/beta/rc tags From e0e5cbb4f4dd232334120793bebe146752b1cd3e Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Fri, 19 Apr 2024 15:53:48 +0400 Subject: [PATCH 208/480] Moved the apply_html_entities function to the end of the formatting.py --- telebot/formatting.py | 210 +++++++++++++++++++++--------------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index 3ececdd65..a491d9404 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -60,111 +60,7 @@ def escape_markdown(content: str) -> str: parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!\{\}\\])", r"\\\1", content) reparse = re.sub(r"\\\\([_*\[\]()~`>\#\+\-=|\.!\{\}\\])", r"\1", parse) - return reparse - - -def apply_html_entities(text: str, entities: Optional[List], custom_subs: Optional[dict[str, str]]) -> str: - """ - Author: @sviat9440 - Updaters: @badiboy, @EgorKhabarov - Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" - - .. code-block:: python3 - :caption: Example: - - apply_html_entities(text, entities) - >> "Test parse formatting, url, text_mention and mention @username" - - Custom subs: - You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. - .. code-block:: python3 - :caption: Example: - - apply_html_entities( - text, - entities, - {"bold": "{text}", "italic": "{text}", "mention": "{text}"}, - ) - >> "Test parse formatting, url and text_mention and mention @username" - """ - - if not entities: - return text.replace("&", "&").replace("<", "<").replace(">", ">") - - _subs = { - "bold": "{text}", - "italic": "{text}", - "pre": "
{text}
", - "code": "{text}", - # "url": "{text}", # @badiboy plain URLs have no text and do not need tags - "text_link": "{text}", - "strikethrough": "{text}", - "underline": "{text}", - "spoiler": "{text}", - "custom_emoji": "{text}", - "blockquote": "
{text}
", - } - - if custom_subs: - for key, value in custom_subs.items(): - _subs[key] = value - utf16_text = text.encode("utf-16-le") - html_text = "" - - def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): - upd_text = upd_text.decode("utf-16-le") - if subst_type == "text_mention": - subst_type = "text_link" - url = "tg://user?id={0}".format(user.id) - elif subst_type == "mention": - url = "https://t.me/{0}".format(upd_text[1:]) - upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") - if not subst_type or not _subs.get(subst_type): - return upd_text - subs = _subs.get(subst_type) - if subst_type == "custom_emoji": - return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) - return subs.format(text=upd_text, url=url) - - offset = 0 - start_index = 0 - end_index = 0 - for entity in entities: - if entity.offset > offset: - # when the offset is not 0: for example, a __b__ - # we need to add the text before the entity to the html_text - html_text += func(utf16_text[offset * 2: entity.offset * 2]) - offset = entity.offset - - new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, - url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) - start_index = len(html_text) - html_text += new_string - offset += entity.length - end_index = len(html_text) - elif entity.offset == offset: - new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, - url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) - start_index = len(html_text) - html_text += new_string - end_index = len(html_text) - offset += entity.length - else: - # Here we are processing nested entities. - # We shouldn't update offset, because they are the same as entity before. - # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, - # And we don't change it). - entity_string = html_text[start_index: end_index].encode("utf-16-le") - formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, - custom_emoji_id=entity.custom_emoji_id). \ - replace("&", "&").replace("<", "<").replace(">", ">") - html_text = html_text[:start_index] + formatted_string + html_text[end_index:] - end_index = len(html_text) - - if offset * 2 < len(utf16_text): - html_text += func(utf16_text[offset * 2:]) - - return html_text + return reparse def mbold(content: str, escape: Optional[bool]=True) -> str: @@ -459,3 +355,107 @@ def hcite(content: str, escape: Optional[bool]=True) -> str: :rtype: :obj:`str` """ return '
{}
'.format(escape_html(content) if escape else content) + + +def apply_html_entities(text: str, entities: Optional[List], custom_subs: Optional[dict[str, str]]) -> str: + """ + Author: @sviat9440 + Updaters: @badiboy, @EgorKhabarov + Message: "*Test* parse _formatting_, [url](https://example.com), [text_mention](tg://user?id=123456) and mention @username" + + .. code-block:: python3 + :caption: Example: + + apply_html_entities(text, entities) + >> "Test parse formatting, url, text_mention and mention @username" + + Custom subs: + You can customize the substitutes. By default, there is no substitute for the entities: hashtag, bot_command, email. You can add or modify substitute an existing entity. + .. code-block:: python3 + :caption: Example: + + apply_html_entities( + text, + entities, + {"bold": "{text}", "italic": "{text}", "mention": "{text}"}, + ) + >> "Test parse formatting, url and text_mention and mention @username" + """ + + if not entities: + return text.replace("&", "&").replace("<", "<").replace(">", ">") + + _subs = { + "bold": "{text}", + "italic": "{text}", + "pre": "
{text}
", + "code": "{text}", + # "url": "{text}", # @badiboy plain URLs have no text and do not need tags + "text_link": "{text}", + "strikethrough": "{text}", + "underline": "{text}", + "spoiler": "{text}", + "custom_emoji": "{text}", + "blockquote": "
{text}
", + } + + if custom_subs: + for key, value in custom_subs.items(): + _subs[key] = value + utf16_text = text.encode("utf-16-le") + html_text = "" + + def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): + upd_text = upd_text.decode("utf-16-le") + if subst_type == "text_mention": + subst_type = "text_link" + url = "tg://user?id={0}".format(user.id) + elif subst_type == "mention": + url = "https://t.me/{0}".format(upd_text[1:]) + upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") + if not subst_type or not _subs.get(subst_type): + return upd_text + subs = _subs.get(subst_type) + if subst_type == "custom_emoji": + return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) + return subs.format(text=upd_text, url=url) + + offset = 0 + start_index = 0 + end_index = 0 + for entity in entities: + if entity.offset > offset: + # when the offset is not 0: for example, a __b__ + # we need to add the text before the entity to the html_text + html_text += func(utf16_text[offset * 2: entity.offset * 2]) + offset = entity.offset + + new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + offset += entity.length + end_index = len(html_text) + elif entity.offset == offset: + new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + start_index = len(html_text) + html_text += new_string + end_index = len(html_text) + offset += entity.length + else: + # Here we are processing nested entities. + # We shouldn't update offset, because they are the same as entity before. + # And, here we are replacing previous string with a new html-rendered text(previous string is already html-rendered, + # And we don't change it). + entity_string = html_text[start_index: end_index].encode("utf-16-le") + formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, + custom_emoji_id=entity.custom_emoji_id). \ + replace("&", "&").replace("<", "<").replace(">", ">") + html_text = html_text[:start_index] + formatted_string + html_text[end_index:] + end_index = len(html_text) + + if offset * 2 < len(utf16_text): + html_text += func(utf16_text[offset * 2:]) + + return html_text From 189da012092839b611233c5354de6ba39e985c85 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 21 Apr 2024 14:29:01 +0300 Subject: [PATCH 209/480] Pass default parse mode to Media items --- telebot/__init__.py | 6 ++++++ telebot/async_telebot.py | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 823324359..237b8a3f2 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3091,6 +3091,12 @@ def send_media_group( :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ + if media: + # Pass default parse mode to Media items + for media_item in media: + if media_item.parse_mode is None: + media_item.parse_mode = self.parse_mode + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d24a025dd..ace5c1f8e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4502,6 +4502,11 @@ async def send_media_group( :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ + if media: + # Pass default parse mode to Media items + for media_item in media: + if media_item.parse_mode is None: + media_item.parse_mode = self.parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content From 2e3b77590afbee435c1fe1fd60f0729b0518765f Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 21 Apr 2024 14:34:23 +0300 Subject: [PATCH 210/480] Hide token in exception messages --- telebot/__init__.py | 8 +++++++- telebot/async_telebot.py | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 237b8a3f2..85387fc33 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1083,9 +1083,15 @@ def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[boo *args, **kwargs) except Exception as e: if logger_level and logger_level >= logging.ERROR: + e = str(e) + if self.token in e: + e = e.replace(self.token, 'TOKEN') logger.error("Infinity polling exception: %s", str(e)) if logger_level and logger_level >= logging.DEBUG: - logger.error("Exception traceback:\n%s", traceback.format_exc()) + e = traceback.format_exc() + if self.token in e: + e = e.replace(self.token, 'TOKEN') + logger.error("Exception traceback:\n%s", e) time.sleep(3) continue if logger_level and logger_level >= logging.INFO: diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ace5c1f8e..975f2d314 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -367,9 +367,15 @@ async def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Option allowed_updates=allowed_updates, *args, **kwargs) except Exception as e: if logger_level and logger_level >= logging.ERROR: + e = str(e) + if self.token in e: + e = e.replace(self.token, 'TOKEN') logger.error("Infinity polling exception: %s", str(e)) if logger_level and logger_level >= logging.DEBUG: - logger.error("Exception traceback:\n%s", traceback.format_exc()) + e = traceback.format_exc() + if self.token in e: + e = e.replace(self.token, 'TOKEN') + logger.error("Exception traceback:\n%s", e) await asyncio.sleep(3) continue if logger_level and logger_level >= logging.INFO: From 717bcf9e83e8600d2aa6f070541e91f400a8562e Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Sun, 21 Apr 2024 17:32:50 +0400 Subject: [PATCH 211/480] Fixed issue in types for Python 3.8 --- telebot/formatting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index a491d9404..dd7309416 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -6,7 +6,7 @@ import re import html -from typing import Optional, List +from typing import Optional, List, Dict def format_text(*args, separator="\n"): @@ -357,7 +357,7 @@ def hcite(content: str, escape: Optional[bool]=True) -> str: return '
{}
'.format(escape_html(content) if escape else content) -def apply_html_entities(text: str, entities: Optional[List], custom_subs: Optional[dict[str, str]]) -> str: +def apply_html_entities(text: str, entities: Optional[List], custom_subs: Optional[Dict[str, str]]) -> str: """ Author: @sviat9440 Updaters: @badiboy, @EgorKhabarov From 2e2240a7fdddb1174b4b98616fae60d3e71dc6df Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 21 Apr 2024 18:31:45 +0300 Subject: [PATCH 212/480] Replace token part with asterisks --- telebot/__init__.py | 48 +++++++++++++++++++++++----------------- telebot/async_telebot.py | 13 +++++++---- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 85387fc33..ca48caae9 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1030,6 +1030,11 @@ def _setup_change_detector(self, path_to_watch: str): self.event_observer.schedule(self.event_handler, path, recursive=True) self.event_observer.start() + def __hide_token(self, message: str) -> str: + if self.token in message: + code = self.token.split(':')[1] + return message.replace(code, "*" * len(code)) + def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[bool]=False, long_polling_timeout: Optional[int]=20, logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None, restart_on_change: Optional[bool]=False, path_to_watch: Optional[str]=None, *args, **kwargs): @@ -1083,15 +1088,9 @@ def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[boo *args, **kwargs) except Exception as e: if logger_level and logger_level >= logging.ERROR: - e = str(e) - if self.token in e: - e = e.replace(self.token, 'TOKEN') - logger.error("Infinity polling exception: %s", str(e)) + logger.error("Infinity polling exception: %s", self.__hide_token(str(e))) if logger_level and logger_level >= logging.DEBUG: - e = traceback.format_exc() - if self.token in e: - e = e.replace(self.token, 'TOKEN') - logger.error("Exception traceback:\n%s", e) + logger.error("Exception traceback:\n%s", self.__hide_token(traceback.format_exc())) time.sleep(3) continue if logger_level and logger_level >= logging.INFO: @@ -6807,7 +6806,7 @@ def register_message_handler(self, callback: Callable, content_types: Optional[L :param commands: list of commands :type commands: :obj:`list` of :obj:`str` - :param regexp: + :param regexp: Regular expression :type regexp: :obj:`str` :param func: Function executed as a filter @@ -7965,6 +7964,7 @@ def register_removed_chat_boost_handler( handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_removed_chat_boost_handler(handler_dict) + def business_connection_handler(self, func=None, **kwargs): """ Handles new incoming business connection state. @@ -7981,7 +7981,8 @@ def decorator(handler): return handler return decorator - + + def add_business_connection_handler(self, handler_dict): """ Adds a business_connection handler. @@ -7994,6 +7995,7 @@ def add_business_connection_handler(self, handler_dict): """ self.business_connection_handlers.append(handler_dict) + def register_business_connection_handler( self, callback: Callable, func: Optional[Callable]=None, pass_bot:Optional[bool]=False, **kwargs): """ @@ -8015,6 +8017,7 @@ def register_business_connection_handler( handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_business_connection_handler(handler_dict) + def business_message_handler( self, commands: Optional[List[str]]=None, @@ -8096,7 +8099,8 @@ def decorator(handler): return handler return decorator - + + def add_business_message_handler(self, handler_dict): """ Adds a business_message handler. @@ -8109,6 +8113,7 @@ def add_business_message_handler(self, handler_dict): """ self.business_message_handlers.append(handler_dict) + def register_business_message_handler(self, callback: Callable, commands: Optional[List[str]]=None, @@ -8122,11 +8127,17 @@ def register_business_message_handler(self, :param callback: function to be called :type callback: :obj:`function` + :param commands: list of commands + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Regular expression + :type regexp: :obj:`str` + :param func: Function executed as a filter :type func: :obj:`function` - :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) - :type pass_bot: :obj:`bool` + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` :param kwargs: Optional keyword arguments(custom filters) @@ -8135,8 +8146,6 @@ def register_business_message_handler(self, handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, **kwargs) self.add_business_message_handler(handler_dict) - - def edited_business_message_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs): """ @@ -8253,7 +8262,7 @@ def register_edited_business_message_handler(self, callback: Callable, content_t **kwargs) self.add_edited_business_message_handler(handler_dict) - + def deleted_business_messages_handler(self, func=None, **kwargs): """ Handles new incoming deleted messages state. @@ -8272,7 +8281,8 @@ def decorator(handler): return handler return decorator - + + def add_deleted_business_messages_handler(self, handler_dict): """ Adds a deleted_business_messages handler. @@ -8282,6 +8292,7 @@ def add_deleted_business_messages_handler(self, handler_dict): """ self.deleted_business_messages_handlers.append(handler_dict) + def register_deleted_business_messages_handler(self, callback: Callable, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ Registers deleted business messages handler. @@ -8304,9 +8315,6 @@ def register_deleted_business_messages_handler(self, callback: Callable, func: O self.add_deleted_business_messages_handler(handler_dict) - - - def add_custom_filter(self, custom_filter: Union[SimpleCustomFilter, AdvancedCustomFilter]): """ Create custom filter. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 975f2d314..01a8a1171 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -393,6 +393,11 @@ async def _handle_exception(self, exception: Exception) -> bool: handled = self.exception_handler.handle(exception) # noqa return handled + def __hide_token(self, message: str) -> str: + if self.token in message: + code = self.token.split(':')[1] + return message.replace(code, "*" * len(code)) + async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: int=20, request_timeout: int=None, allowed_updates: Optional[List[str]]=None): """ @@ -442,8 +447,8 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: except asyncio_helper.RequestTimeout as e: handled = await self._handle_exception(e) if not handled: - logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) - logger.debug(traceback.format_exc()) + logger.error('Unhandled exception (full traceback for debug level): %s', self.__hide_token(str(e))) + logger.debug(self.__hide_token(traceback.format_exc())) if non_stop or handled: await asyncio.sleep(2) @@ -453,8 +458,8 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: except asyncio_helper.ApiException as e: handled = await self._handle_exception(e) if not handled: - logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) - logger.debug(traceback.format_exc()) + logger.error('Unhandled exception (full traceback for debug level): %s', self.__hide_token(str(e))) + logger.debug(self.__hide_token(traceback.format_exc())) if non_stop or handled: continue From b3053405b3206fe7822e46b4a974971e7fe5db0b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 21 Apr 2024 19:08:49 +0300 Subject: [PATCH 213/480] Replace token part with asterisks N2 --- telebot/__init__.py | 4 ++-- telebot/async_telebot.py | 11 +++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index ca48caae9..067d24d76 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1214,9 +1214,9 @@ def __threaded_polling(self, non_stop = False, interval = 0, timeout = None, lon handled = self._handle_exception(e) if not handled: if logger_level and logger_level >= logging.ERROR: - logger.error("Threaded polling exception: %s", str(e)) + logger.error("Threaded polling exception: %s", self.__hide_token(str(e))) if logger_level and logger_level >= logging.DEBUG: - logger.error("Exception traceback:\n%s", traceback.format_exc()) + logger.error("Exception traceback:\n%s", self.__hide_token(traceback.format_exc())) if not non_stop: self.__stop_polling.set() # if logger_level and logger_level >= logging.INFO: # enable in future releases. Change output to logger.error diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 01a8a1171..bc3ba8d3b 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -367,15 +367,9 @@ async def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Option allowed_updates=allowed_updates, *args, **kwargs) except Exception as e: if logger_level and logger_level >= logging.ERROR: - e = str(e) - if self.token in e: - e = e.replace(self.token, 'TOKEN') - logger.error("Infinity polling exception: %s", str(e)) + logger.error("Infinity polling exception: %s", self.__hide_token(str(e))) if logger_level and logger_level >= logging.DEBUG: - e = traceback.format_exc() - if self.token in e: - e = e.replace(self.token, 'TOKEN') - logger.error("Exception traceback:\n%s", e) + logger.error("Exception traceback:\n%s", self.__hide_token(traceback.format_exc())) await asyncio.sleep(3) continue if logger_level and logger_level >= logging.INFO: @@ -437,6 +431,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: updates = await self.get_updates(offset=self.offset, allowed_updates=allowed_updates, timeout=timeout, request_timeout=request_timeout) if updates: self.offset = updates[-1].update_id + 1 + # noinspection PyAsyncCall asyncio.create_task(self.process_new_updates(updates)) # Seperate task for processing updates if interval: await asyncio.sleep(interval) From 66236eff0a1ab490d3466f966fc4f3940bf54be9 Mon Sep 17 00:00:00 2001 From: YouKnow Date: Wed, 24 Apr 2024 18:55:20 +0330 Subject: [PATCH 214/480] Removed the `_convert_entites` fucntion and used `json.dumps(types.MessageEntity.to_list_of_dicts(...))` method for caption entities --- telebot/apihelper.py | 13 +------------ telebot/asyncio_helper.py | 14 +------------- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 3f537065c..8941b88ae 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -432,7 +432,7 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m if parse_mode: payload['parse_mode'] = parse_mode if caption_entities is not None: - payload['caption_entities'] = _convert_entites(caption_entities) + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if disable_notification is not None: payload['disable_notification'] = disable_notification if reply_parameters is not None: @@ -1998,17 +1998,6 @@ def _convert_markup(markup): return markup -def _convert_entites(entites): - if entites is None: - return None - elif len(entites) == 0: - return [] - elif isinstance(entites[0], types.JsonSerializable): - return [entity.to_json() for entity in entites] - else: - return entites - - def _convert_poll_options(poll_options): if poll_options is None: return None diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 3aadccc65..9c8f6128c 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -422,7 +422,7 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p if parse_mode: payload['parse_mode'] = parse_mode if caption_entities is not None: - payload['caption_entities'] = await _convert_entites(caption_entities) + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if disable_notification is not None: payload['disable_notification'] = disable_notification if reply_parameters is not None: @@ -1975,18 +1975,6 @@ async def _convert_list_json_serializable(results): return '[' + ret + ']' - -async def _convert_entites(entites): - if entites is None: - return None - elif len(entites) == 0: - return [] - elif isinstance(entites[0], types.JsonSerializable): - return [entity.to_json() for entity in entites] - else: - return entites - - async def _convert_poll_options(poll_options): if poll_options is None: return None From 316825be94b7f72524fcbfd1bd31198344467fad Mon Sep 17 00:00:00 2001 From: chiri <109767616+chirizxc@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:33:52 +0300 Subject: [PATCH 215/480] Removed the tautology in the documentation title --- docs/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f2ab5ac09..aa49bceb2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,9 +17,9 @@ # -- Project information ----------------------------------------------------- -project = 'pyTelegramBotAPI Documentation' -copyright = f'2022-{datetime.now().year}, coder2020official' +project = 'pyTelegramBotAPI' author = 'coder2020official' +copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags release = '4.17.0' From e26ee25de0c8a8eece049ffac6ae7bad2c7eb5f4 Mon Sep 17 00:00:00 2001 From: chiri <109767616+chirizxc@users.noreply.github.com> Date: Thu, 25 Apr 2024 20:06:37 +0300 Subject: [PATCH 216/480] Update async echo_bot example --- examples/asynchronous_telebot/echo_bot.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/asynchronous_telebot/echo_bot.py b/examples/asynchronous_telebot/echo_bot.py index cd2353755..aed26675e 100644 --- a/examples/asynchronous_telebot/echo_bot.py +++ b/examples/asynchronous_telebot/echo_bot.py @@ -2,19 +2,18 @@ # This is a simple echo bot using the decorator mechanism. # It echoes any incoming text messages. +import asyncio from telebot.async_telebot import AsyncTeleBot -bot = AsyncTeleBot('TOKEN') +bot = AsyncTeleBot('TOKEN') # Handle '/start' and '/help' @bot.message_handler(commands=['help', 'start']) async def send_welcome(message): - await bot.reply_to(message, """\ -Hi there, I am EchoBot. -I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\ -""") + text = 'Hi, I am EchoBot.\nJust write me something and I will repeat it!' + await bot.reply_to(message, text) # Handle all other messages with content_type 'text' (content_types defaults to ['text']) @@ -23,5 +22,4 @@ async def echo_message(message): await bot.reply_to(message, message.text) -import asyncio asyncio.run(bot.polling()) From 1b6a57381cd14cc90f0030a014869f3cbac28d92 Mon Sep 17 00:00:00 2001 From: YouKnow Date: Thu, 25 Apr 2024 22:40:54 +0330 Subject: [PATCH 217/480] added some of `_convert_entities` checks to `to_list_of_dicts` --- telebot/types.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 7c2782788..51db25ab5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1612,10 +1612,12 @@ def to_list_of_dicts(entity_list) -> Union[List[Dict], None]: """ Converts a list of MessageEntity objects to a list of dictionaries. """ - res = [] - for e in entity_list: - res.append(MessageEntity.to_dict(e)) - return res or None + if entity_list is None or len(entity_list) == 0: + return None + elif isinstance(entity_list[0], MessageEntity): + return [MessageEntity.to_dict(e) for e in entity_list] + else: + return entity_list @classmethod def de_json(cls, json_string): From 776bd53cc1544108887378367746c7b365f4b4ec Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Fri, 26 Apr 2024 16:14:10 +0400 Subject: [PATCH 218/480] Fixed a bug with hiding the token --- telebot/__init__.py | 2 ++ telebot/async_telebot.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 067d24d76..3da8952be 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1034,6 +1034,8 @@ def __hide_token(self, message: str) -> str: if self.token in message: code = self.token.split(':')[1] return message.replace(code, "*" * len(code)) + else: + return message def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[bool]=False, long_polling_timeout: Optional[int]=20, logger_level: Optional[int]=logging.ERROR, allowed_updates: Optional[List[str]]=None, diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 36b6d007b..fa4a0a7eb 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -391,6 +391,8 @@ def __hide_token(self, message: str) -> str: if self.token in message: code = self.token.split(':')[1] return message.replace(code, "*" * len(code)) + else: + return message async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: int=20, request_timeout: int=None, allowed_updates: Optional[List[str]]=None): From 44531cded17aa82d8618154b9ede558a2f826225 Mon Sep 17 00:00:00 2001 From: Shakhzhakhan Maxudbek Date: Sun, 28 Apr 2024 00:17:25 +0500 Subject: [PATCH 219/480] Added Flask Google Cloud bot's example --- .../flask_google_cloud_bot/.gcloudignore | 1 + .../flask_google_cloud_bot/app.yaml | 4 ++ .../serverless/flask_google_cloud_bot/main.py | 65 +++++++++++++++++++ .../flask_google_cloud_bot/requirements.txt | 14 ++++ 4 files changed, 84 insertions(+) create mode 100644 examples/serverless/flask_google_cloud_bot/.gcloudignore create mode 100644 examples/serverless/flask_google_cloud_bot/app.yaml create mode 100644 examples/serverless/flask_google_cloud_bot/main.py create mode 100644 examples/serverless/flask_google_cloud_bot/requirements.txt diff --git a/examples/serverless/flask_google_cloud_bot/.gcloudignore b/examples/serverless/flask_google_cloud_bot/.gcloudignore new file mode 100644 index 000000000..ae412d6a0 --- /dev/null +++ b/examples/serverless/flask_google_cloud_bot/.gcloudignore @@ -0,0 +1 @@ +env/ \ No newline at end of file diff --git a/examples/serverless/flask_google_cloud_bot/app.yaml b/examples/serverless/flask_google_cloud_bot/app.yaml new file mode 100644 index 000000000..59ad3ad6f --- /dev/null +++ b/examples/serverless/flask_google_cloud_bot/app.yaml @@ -0,0 +1,4 @@ +runtime: python38 + +env_variables: + BUCKET_NAME: "your-google-application" \ No newline at end of file diff --git a/examples/serverless/flask_google_cloud_bot/main.py b/examples/serverless/flask_google_cloud_bot/main.py new file mode 100644 index 000000000..67f479ff6 --- /dev/null +++ b/examples/serverless/flask_google_cloud_bot/main.py @@ -0,0 +1,65 @@ +''' +Simple bot for Google cloud deployment. + +Docs: +https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service + +1. Receive your bot's token from https://t.me/BotFather + +2. Create a Google Cloud project. https://cloud.google.com/resource-manager/docs/creating-managing-projects + +3. Install the Google Cloud CLI. https://cloud.google.com/sdk/docs/install + +4. Move to telegram_google_cloud_bot folder + +cd telegram_google_cloud_bot/ + +5. Initialize the gcloud CLI: + +gcloud init + +6. To set the default project for your Cloud Run service: + +gcloud config set project PROJECT_ID + +7. Deploy: + +gcloud run deploy +''' + +import os + +from flask import Flask, request + +import telebot + +TOKEN = 'token_from_botfather' + +bot = telebot.TeleBot(TOKEN) + +app = Flask(__name__) + + +@bot.message_handler(commands=['start']) +def start(message): + bot.reply_to(message, 'Hello, ' + message.from_user.first_name) + + +@bot.message_handler(func=lambda message: True, content_types=['text']) +def echo_message(message): + bot.reply_to(message, message.text) + + +@app.route('/' + TOKEN, methods=['POST']) +def getMessage(): + json_string = request.get_data().decode('utf-8') + update = telebot.types.Update.de_json(json_string) + bot.process_new_updates([update]) + return '!', 200 + + +@app.route('/') +def webhook(): + bot.remove_webhook() + bot.set_webhook(url='https://mydomain.com/' + TOKEN) + return '!', 200 \ No newline at end of file diff --git a/examples/serverless/flask_google_cloud_bot/requirements.txt b/examples/serverless/flask_google_cloud_bot/requirements.txt new file mode 100644 index 000000000..6fca88a25 --- /dev/null +++ b/examples/serverless/flask_google_cloud_bot/requirements.txt @@ -0,0 +1,14 @@ +certifi==2022.12.7 +charset-normalizer==3.1.0 +click==8.0.3 +Flask==2.0.2 +idna==3.4 +importlib-metadata==6.4.1 +itsdangerous==2.0.1 +Jinja2==3.0.3 +MarkupSafe==2.0.1 +pyTelegramBotAPI==4.11.0 +requests==2.28.2 +urllib3==1.26.15 +Werkzeug==2.0.2 +zipp==3.15.0 From 5641674ac9d0b682bb2a39f62b9220c5c7ef1dce Mon Sep 17 00:00:00 2001 From: smartwa Date: Sun, 28 Apr 2024 18:42:35 +0300 Subject: [PATCH 220/480] Add pytgpt-bot as bot using this library --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 20b062e70..3f11bf8f9 100644 --- a/README.md +++ b/README.md @@ -890,5 +890,6 @@ Here are some examples of template: * [Best Instagram Downloader Bot](https://t.me/Best_Instagram_Downloader_Bot) ([source](https://github.com/arashnm80/best-instagram-downloader)) by [Arashnm80](https://github.com/arashnm80). Free and open source telegram bot to download posts and reels from Instagram. * [4K YouTube Downloader](https://github.com/hansanaD/TelegramYTDLBot/) - Youtube Downloader with upto 4K resolution support. * [DrinkGenius-Bot](https://t.me/cocktail_recommendation_bot) ([source](https://github.com/Povladarchik/DrinkGenius-Bot)) by [Povladarchik](https://github.com/Povladarchik). Your personal assistant in the world of cocktails. +* [Pytgpt-Bot](https://t.me/pytgpt_bot) ([source](https://github.com/Simatwa/pytgpt-bot)) by [Smartwa](https://github.com/Simatwa). AI powered bot for chatting, text-to-image and text-to-speech conversions. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From c82e3db719c639255e10759458482c5d1d402165 Mon Sep 17 00:00:00 2001 From: Shakhzhakhan Maxudbek <153020509+xinitd@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:18:34 +0500 Subject: [PATCH 221/480] Update requirements.txt. Fix dependencies --- .../flask_google_cloud_bot/requirements.txt | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/examples/serverless/flask_google_cloud_bot/requirements.txt b/examples/serverless/flask_google_cloud_bot/requirements.txt index 6fca88a25..b4bb7413e 100644 --- a/examples/serverless/flask_google_cloud_bot/requirements.txt +++ b/examples/serverless/flask_google_cloud_bot/requirements.txt @@ -1,14 +1,4 @@ -certifi==2022.12.7 -charset-normalizer==3.1.0 -click==8.0.3 -Flask==2.0.2 -idna==3.4 -importlib-metadata==6.4.1 -itsdangerous==2.0.1 -Jinja2==3.0.3 -MarkupSafe==2.0.1 pyTelegramBotAPI==4.11.0 -requests==2.28.2 -urllib3==1.26.15 -Werkzeug==2.0.2 -zipp==3.15.0 +Flask==3.0.0 +gunicorn==22.0.0 +Werkzeug==3.0.1 From a7379a6a55a2b9b4f58b793c3f9cf4c03492d3d0 Mon Sep 17 00:00:00 2001 From: vehlwn <36479428+vehlwn@users.noreply.github.com> Date: Wed, 1 May 2024 18:26:28 +0400 Subject: [PATCH 222/480] Add type hints to SimpleCustomFilter --- telebot/asyncio_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index 72695e90b..c580883ee 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -27,7 +27,7 @@ def check(self, message): key: str = None - async def check(self, message): + async def check(self, message: types.Message) -> bool: """ Perform a check. """ From 25f97213793818662ad80104a202ff6c12e2fe59 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 1 May 2024 20:44:04 +0300 Subject: [PATCH 223/480] Revert add type hints to SimpleCustomFilter --- telebot/asyncio_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index c580883ee..da794b77b 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -27,7 +27,7 @@ def check(self, message): key: str = None - async def check(self, message: types.Message) -> bool: + async def check(self, message) -> bool: """ Perform a check. """ From 374fe91068a66a6fa1d91668f821a9565dd68066 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 19:42:20 +0000 Subject: [PATCH 224/480] Bump werkzeug in /examples/serverless/flask_google_cloud_bot Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.0.1 to 3.0.3. - [Release notes](https://github.com/pallets/werkzeug/releases) - [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/werkzeug/compare/3.0.1...3.0.3) --- updated-dependencies: - dependency-name: werkzeug dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- examples/serverless/flask_google_cloud_bot/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/serverless/flask_google_cloud_bot/requirements.txt b/examples/serverless/flask_google_cloud_bot/requirements.txt index b4bb7413e..ed0491b0a 100644 --- a/examples/serverless/flask_google_cloud_bot/requirements.txt +++ b/examples/serverless/flask_google_cloud_bot/requirements.txt @@ -1,4 +1,4 @@ pyTelegramBotAPI==4.11.0 Flask==3.0.0 gunicorn==22.0.0 -Werkzeug==3.0.1 +Werkzeug==3.0.3 From be440a155ac416f75632a962cbfd65773ef659e9 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 11:39:44 +0300 Subject: [PATCH 225/480] Init BOT API 7.3 with version bump --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index aa49bceb2..bb40d90ab 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.17.0' +release = '4.18.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index fde7a8685..6666fee8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.17.0" +version = "4.18.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 3eb8b787f..4ee703d3d 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.17.0' +__version__ = '4.18.0' From 8a185b9f0cd362807a33c04295a6a4bb42404de3 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 11:46:14 +0300 Subject: [PATCH 226/480] Added the field via_join_request to the class ChatMemberUpdated. --- telebot/types.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 51db25ab5..34e7ab328 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -284,6 +284,9 @@ class ChatMemberUpdated(JsonDeserializable): link events only. :type invite_link: :class:`telebot.types.ChatInviteLink` + :param via_join_request: Optional. True, if the user joined the chat after sending a direct join request without using an invite link and being approved by an administrator + :type via_join_request: :obj:`bool` + :param via_chat_folder_invite_link: Optional. True, if the user joined the chat via a chat folder invite link :type via_chat_folder_invite_link: :obj:`bool` @@ -301,7 +304,8 @@ def de_json(cls, json_string): obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link')) return cls(**obj) - def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, via_chat_folder_invite_link=None, + def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, + via_join_request=None, via_chat_folder_invite_link=None, **kwargs): self.chat: Chat = chat self.from_user: User = from_user @@ -309,8 +313,9 @@ def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invi self.old_chat_member: ChatMember = old_chat_member self.new_chat_member: ChatMember = new_chat_member self.invite_link: Optional[ChatInviteLink] = invite_link + self.via_join_request: Optional[bool] = via_join_request self.via_chat_folder_invite_link: Optional[bool] = via_chat_folder_invite_link - + @property def difference(self) -> Dict[str, List]: """ From 0e462918d844c262baf5e409314aeaf18c7068d0 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 11:50:31 +0300 Subject: [PATCH 227/480] Documented that .MP3 and .M4A files can be used as voice messages. --- telebot/__init__.py | 4 +--- telebot/async_telebot.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 3da8952be..d953df750 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2356,9 +2356,7 @@ def send_voice( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None) -> types.Message: """ - Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. - For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). - On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. + Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. Telegram documentation: https://core.telegram.org/bots/api#sendvoice diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index fa4a0a7eb..473a06436 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3764,9 +3764,7 @@ async def send_voice( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None) -> types.Message: """ - Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. - For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). - On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. + Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. Telegram documentation: https://core.telegram.org/bots/api#sendvoice From bf8c6f765c8f13759c05449bc41fcca091b62c2d Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 11:55:17 +0300 Subject: [PATCH 228/480] Added support for live locations that can be edited indefinitely, allowing 0x7FFFFFFF to be used as live_period. --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- telebot/types.py | 18 ++++++------------ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d953df750..15bfd5dc0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3160,7 +3160,7 @@ def send_location( :param longitude: Longitude of the location :type longitude: :obj:`float` - :param live_period: Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400. + :param live_period: Period in seconds during which the location will be updated (see Live Locations, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. :type live_period: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 473a06436..435f74428 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4571,7 +4571,7 @@ async def send_location( :param longitude: Longitude of the location :type longitude: :obj:`float` - :param live_period: Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400. + :param live_period: Period in seconds during which the location will be updated (see Live Locations, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. :type live_period: :obj:`int` :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message diff --git a/telebot/types.py b/telebot/types.py index 34e7ab328..0ae4c53c0 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3897,16 +3897,13 @@ class InputLocationMessageContent(Dictionaryable): :param horizontal_accuracy: Optional. The radius of uncertainty for the location, measured in meters; 0-1500 :type horizontal_accuracy: :obj:`float` number - :param live_period: Optional. Period in seconds for which the location can be updated, should be between 60 and - 86400. + :param live_period: Optional. Period in seconds during which the location can be updated, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. :type live_period: :obj:`int` - :param heading: Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 - and 360 if specified. + :param heading: Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. :type heading: :obj:`int` - :param proximity_alert_radius: Optional. For live locations, a maximum distance for proximity alerts about - approaching another chat member, in meters. Must be between 1 and 100000 if specified. + :param proximity_alert_radius: Optional. For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` :return: Instance of the class @@ -4999,16 +4996,13 @@ class InlineQueryResultLocation(InlineQueryResultBase): :param horizontal_accuracy: Optional. The radius of uncertainty for the location, measured in meters; 0-1500 :type horizontal_accuracy: :obj:`float` number - :param live_period: Optional. Period in seconds for which the location can be updated, should be between 60 and - 86400. + :param live_period: Optional. Period in seconds during which the location can be updated, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. :type live_period: :obj:`int` - :param heading: Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 - and 360 if specified. + :param heading: Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. :type heading: :obj:`int` - :param proximity_alert_radius: Optional. For live locations, a maximum distance for proximity alerts about - approaching another chat member, in meters. Must be between 1 and 100000 if specified. + :param proximity_alert_radius: Optional. For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` :param reply_markup: Optional. Inline keyboard attached to the message From 51db7de19c24d31090b38a1a6d4228faeae25fd9 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 12:27:17 +0300 Subject: [PATCH 229/480] Added the parameter live_period to the method editMessageLiveLocation. --- telebot/__init__.py | 9 +++++++-- telebot/apihelper.py | 7 ++++--- telebot/async_telebot.py | 10 ++++++++-- telebot/asyncio_helper.py | 9 +++++---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 15bfd5dc0..10c8302bc 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3243,7 +3243,9 @@ def edit_message_live_location( timeout: Optional[int]=None, horizontal_accuracy: Optional[float]=None, heading: Optional[int]=None, - proximity_alert_radius: Optional[int]=None) -> types.Message or bool: + proximity_alert_radius: Optional[int]=None, + live_period: Optional[int]=None, + ) -> types.Message or bool: """ Use this method to edit live location messages. A location can be edited until its live_period expires or editing is explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message is not an inline message, the edited Message @@ -3282,6 +3284,9 @@ def edit_message_live_location( :param proximity_alert_radius: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` + :param live_period: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. + :type live_period: :obj:`int` + :return: On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. :rtype: :class:`telebot.types.Message` or bool """ @@ -3289,7 +3294,7 @@ def edit_message_live_location( apihelper.edit_message_live_location( self.token, latitude, longitude, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, reply_markup=reply_markup, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, - proximity_alert_radius=proximity_alert_radius) + proximity_alert_radius=proximity_alert_radius, live_period=live_period) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 8941b88ae..0dd7e54d6 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -572,9 +572,8 @@ def send_location( def edit_message_live_location( - token, latitude, longitude, chat_id=None, message_id=None, - inline_message_id=None, reply_markup=None, timeout=None, - horizontal_accuracy=None, heading=None, proximity_alert_radius=None): + token, latitude, longitude, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, + timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, live_period=None): method_url = r'editMessageLiveLocation' payload = {'latitude': latitude, 'longitude': longitude} if chat_id: @@ -587,6 +586,8 @@ def edit_message_live_location( payload['heading'] = heading if proximity_alert_radius: payload['proximity_alert_radius'] = proximity_alert_radius + if live_period: + payload['live_period'] = live_period if inline_message_id: payload['inline_message_id'] = inline_message_id if reply_markup: diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 435f74428..f35f092fb 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4655,7 +4655,9 @@ async def edit_message_live_location( timeout: Optional[int]=None, horizontal_accuracy: Optional[float]=None, heading: Optional[int]=None, - proximity_alert_radius: Optional[int]=None) -> types.Message: + proximity_alert_radius: Optional[int]=None, + live_period: Optional[int]=None, + ) -> types.Message: """ Use this method to edit live location messages. A location can be edited until its live_period expires or editing is explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message is not an inline message, the edited Message @@ -4694,6 +4696,9 @@ async def edit_message_live_location( :param proximity_alert_radius: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` + :param live_period: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. + :type live_period: :obj:`int` + :return: On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. :rtype: :class:`telebot.types.Message` or bool """ @@ -4701,7 +4706,8 @@ async def edit_message_live_location( await asyncio_helper.edit_message_live_location( self.token, latitude, longitude, chat_id, message_id, inline_message_id, reply_markup, timeout, - horizontal_accuracy, heading, proximity_alert_radius)) + horizontal_accuracy, heading, proximity_alert_radius, live_period=live_period) + ) async def stop_message_live_location( self, chat_id: Optional[Union[int, str]]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 9c8f6128c..142491a3e 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -564,9 +564,8 @@ async def send_location( async def edit_message_live_location( - token, latitude, longitude, chat_id=None, message_id=None, - inline_message_id=None, reply_markup=None, timeout=None, - horizontal_accuracy=None, heading=None, proximity_alert_radius=None): + token, latitude, longitude, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, + timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, live_period=None): method_url = r'editMessageLiveLocation' payload = {'latitude': latitude, 'longitude': longitude} if chat_id: @@ -579,8 +578,10 @@ async def edit_message_live_location( payload['heading'] = heading if proximity_alert_radius: payload['proximity_alert_radius'] = proximity_alert_radius + if live_period: + payload['live_period'] = live_period if inline_message_id: - payload['inline_message_id'] = inline_message_id + payload['inline_message_id'] = inline_message_id\ if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: From 71346d8701265f8e952e87d515d258c1d4b8f5a2 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 12:31:02 +0300 Subject: [PATCH 230/480] Added the parameter live_period to the method editMessageLiveLocation u1 --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 10c8302bc..c82a23c37 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3284,7 +3284,7 @@ def edit_message_live_location( :param proximity_alert_radius: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` - :param live_period: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. + :param live_period: New period in seconds during which the location can be updated, starting from the message send date. If 0x7FFFFFFF is specified, then the location can be updated forever. Otherwise, the new value must not exceed the current live_period by more than a day, and the live location expiration date must remain within the next 90 days. If not specified, then live_period remains unchanged :type live_period: :obj:`int` :return: On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index f35f092fb..8968a3c0f 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4696,7 +4696,7 @@ async def edit_message_live_location( :param proximity_alert_radius: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. :type proximity_alert_radius: :obj:`int` - :param live_period: The maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. + :param live_period: New period in seconds during which the location can be updated, starting from the message send date. If 0x7FFFFFFF is specified, then the location can be updated forever. Otherwise, the new value must not exceed the current live_period by more than a day, and the live location expiration date must remain within the next 90 days. If not specified, then live_period remains unchanged :type live_period: :obj:`int` :return: On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. From 1a562e566f98326a6a08a08b53bdc996ba1a35c2 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 12:38:46 +0300 Subject: [PATCH 231/480] Added the field question_entities to the class Poll. --- telebot/types.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 0ae4c53c0..aa0026558 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6916,16 +6916,13 @@ class Poll(JsonDeserializable): :param allows_multiple_answers: True, if the poll allows multiple answers :type allows_multiple_answers: :obj:`bool` - :param correct_option_id: Optional. 0-based identifier of the correct answer option. Available only for polls in - the quiz mode, which are closed, or was sent (not forwarded) by the bot or to the private chat with the bot. + :param correct_option_id: Optional. 0-based identifier of the correct answer option. Available only for polls in the quiz mode, which are closed, or was sent (not forwarded) by the bot or to the private chat with the bot. :type correct_option_id: :obj:`int` - :param explanation: Optional. Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a - quiz-style poll, 0-200 characters + :param explanation: Optional. Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters :type explanation: :obj:`str` - :param explanation_entities: Optional. Special entities like usernames, URLs, bot commands, etc. that appear in - the explanation + :param explanation_entities: Optional. Special entities like usernames, URLs, bot commands, etc. that appear in the explanation :type explanation_entities: :obj:`list` of :class:`telebot.types.MessageEntity` :param open_period: Optional. Amount of time in seconds the poll will be active after creation @@ -6934,6 +6931,9 @@ class Poll(JsonDeserializable): :param close_date: Optional. Point in time (Unix timestamp) when the poll will be automatically closed :type close_date: :obj:`int` + :param question_entities: Optional. Special entities that appear in the question. Currently, only custom emoji entities are allowed in poll questions + :type question_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :return: Instance of the class :rtype: :class:`telebot.types.Poll` """ @@ -6948,6 +6948,8 @@ def de_json(cls, json_string): obj['options'] = options or None if 'explanation_entities' in obj: obj['explanation_entities'] = Message.parse_entities(obj['explanation_entities']) + if 'question_entities' in obj: + obj['question_entities'] = Message.parse_entities(obj['question_entities']) return cls(**obj) # noinspection PyShadowingBuiltins @@ -6956,7 +6958,8 @@ def __init__( question, options, poll_id=None, total_voter_count=None, is_closed=None, is_anonymous=None, type=None, allows_multiple_answers=None, correct_option_id=None, explanation=None, explanation_entities=None, - open_period=None, close_date=None, poll_type=None, **kwargs): + open_period=None, close_date=None, poll_type=None, question_entities=None, + **kwargs): self.id: str = poll_id self.question: str = question self.options: List[PollOption] = options @@ -6972,6 +6975,7 @@ def __init__( self.correct_option_id: int = correct_option_id self.explanation: str = explanation self.explanation_entities: List[MessageEntity] = explanation_entities + self.question_entities: List[MessageEntity] = question_entities self.open_period: int = open_period self.close_date: int = close_date From 4bee6ffbda67fcbe1daba951016180a581eed343 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 12:48:50 +0300 Subject: [PATCH 232/480] Added the field questiAdded the field question_entities to the class Poll.on_entities to the class Poll. --- telebot/types.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index aa0026558..3b350dbfc 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6868,6 +6868,9 @@ class PollOption(JsonDeserializable): :param voter_count: Number of users that voted for this option :type voter_count: :obj:`int` + :param text_entities: Optional. Special entities that appear in the option text. Currently, only custom emoji entities are allowed in poll option texts + :type text_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :return: Instance of the class :rtype: :class:`telebot.types.PollOption` """ @@ -6875,11 +6878,14 @@ class PollOption(JsonDeserializable): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) + if 'text_entities' in obj: + obj['text_entities'] = Message.parse_entities(obj['text_entities']) return cls(**obj) - def __init__(self, text, voter_count = 0, **kwargs): + def __init__(self, text, voter_count = 0, text_entities=None, **kwargs): self.text: str = text self.voter_count: int = voter_count + self.text_entities: List[MessageEntity] = text_entities # Converted in _convert_poll_options # def to_json(self): # # send_poll Option is a simple string: https://core.telegram.org/bots/api#sendpoll From 9c64ad2345aa6ff4a480ea63a732e11debfa1988 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 13:04:51 +0300 Subject: [PATCH 233/480] Added the parameters question_parse_mode and question_entities to the method sendPoll. --- telebot/__init__.py | 27 +++++++++++++++++---------- telebot/apihelper.py | 27 +++++++++++++++------------ telebot/async_telebot.py | 15 +++++++++++++-- telebot/asyncio_helper.py | 8 ++++++-- 4 files changed, 51 insertions(+), 26 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index c82a23c37..b76dbccce 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5150,7 +5150,10 @@ def send_poll( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + question_parse_mode: Optional[str] = None, + question_entities: Optional[List[types.MessageEntity]] = None, + ) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -5175,12 +5178,10 @@ def send_poll( :param allows_multiple_answers: True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False :type allows_multiple_answers: :obj:`bool` - :param correct_option_id: 0-based identifier of the correct answer option. Available only for polls in quiz mode, - defaults to None + :param correct_option_id: 0-based identifier of the correct answer option. Available only for polls in quiz mode, defaults to None :type correct_option_id: :obj:`int` - :param explanation: Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, - 0-200 characters with at most 2 line feeds after entities parsing + :param explanation: Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing :type explanation: :obj:`str` :param explanation_parse_mode: Mode for parsing entities in the explanation. See formatting options for more details. @@ -5204,15 +5205,13 @@ def send_poll( :param allow_sending_without_reply: deprecated. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` - :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, - instructions to remove reply keyboard or to force a reply from the user. + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. :type reply_markup: :obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`ForceReply` :param timeout: Timeout in seconds for waiting for a response from the user. :type timeout: :obj:`int` - :param explanation_entities: A JSON-serialized list of special entities that appear in the explanation, - which can be specified instead of parse_mode + :param explanation_entities: A JSON-serialized list of special entities that appear in the explanation, which can be specified instead of parse_mode :type explanation_entities: :obj:`list` of :obj:`MessageEntity` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -5227,6 +5226,12 @@ def send_poll( :param business_connection_id: Identifier of the business connection to use for the poll :type business_connection_id: :obj:`str` + :param question_parse_mode: Mode for parsing entities in the question. See formatting options for more details. Currently, only custom emoji entities are allowed + :type question_parse_mode: :obj:`str` + + :param question_entities: A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question_parse_mode + :type question_entities: :obj:`list` of :obj:`MessageEntity` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5258,6 +5263,7 @@ def send_poll( raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode + question_parse_mode = self.parse_mode if (question_parse_mode is None) else question_parse_mode return types.Message.de_json( apihelper.send_poll( @@ -5268,7 +5274,8 @@ def send_poll( close_date=close_date, is_closed=is_closed, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, explanation_entities=explanation_entities, protect_content=protect_content, message_thread_id=message_thread_id, - reply_parameters=reply_parameters, business_connection_id=business_connection_id) + reply_parameters=reply_parameters, business_connection_id=business_connection_id, + question_parse_mode=question_parse_mode, question_entities=question_entities) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 0dd7e54d6..5a22d5f5a 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1818,8 +1818,8 @@ def send_poll( question, options, is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, - reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, - business_connection_id=None): + reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, + reply_parameters=None, business_connection_id=None, question_parse_mode=None, question_entities=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1828,19 +1828,19 @@ def send_poll( if is_anonymous is not None: payload['is_anonymous'] = is_anonymous - if type is not None: + if type: payload['type'] = type if allows_multiple_answers is not None: payload['allows_multiple_answers'] = allows_multiple_answers if correct_option_id is not None: payload['correct_option_id'] = correct_option_id - if explanation is not None: + if explanation: payload['explanation'] = explanation - if explanation_parse_mode is not None: + if explanation_parse_mode: payload['explanation_parse_mode'] = explanation_parse_mode - if open_period is not None: + if open_period: payload['open_period'] = open_period - if close_date is not None: + if close_date: if isinstance(close_date, datetime): payload['close_date'] = close_date.timestamp() else: @@ -1849,21 +1849,24 @@ def send_poll( payload['is_closed'] = is_closed if disable_notification: payload['disable_notification'] = disable_notification - if reply_markup is not None: + if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout if explanation_entities: - payload['explanation_entities'] = json.dumps( - types.MessageEntity.to_list_of_dicts(explanation_entities)) + payload['explanation_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(explanation_entities)) if protect_content: payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id - if reply_parameters is not None: + if reply_parameters: payload['reply_parameters'] = reply_parameters.to_json() - if business_connection_id is not None: + if business_connection_id: payload['business_connection_id'] = business_connection_id + if question_parse_mode: + payload['question_parse_mode'] = question_parse_mode + if question_entities: + payload['question_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(question_entities)) return _make_request(token, method_url, params=payload) def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8968a3c0f..fcbd2fc1a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6495,7 +6495,10 @@ async def send_poll( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + question_parse_mode: Optional[str] = None, + question_entities: Optional[List[types.MessageEntity]] = None, + ) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -6572,6 +6575,12 @@ async def send_poll( :param business_connection_id: Identifier of the business connection to send the message through :type business_connection_id: :obj:`str` + :param question_parse_mode: Mode for parsing entities in the question. See formatting options for more details. Currently, only custom emoji entities are allowed + :type question_parse_mode: :obj:`str` + + :param question_entities: A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question_parse_mode + :type question_entities: :obj:`list` of :obj:`MessageEntity` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6579,6 +6588,7 @@ async def send_poll( protect_content = self.protect_content if (protect_content is None) else protect_content explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode + question_parse_mode = self.parse_mode if (question_parse_mode is None) else question_parse_mode if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") @@ -6610,7 +6620,8 @@ async def send_poll( is_anonymous, type, allows_multiple_answers, correct_option_id, explanation, explanation_parse_mode, open_period, close_date, is_closed, disable_notification, - reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters, business_connection_id)) + reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters, + business_connection_id, question_parse_mode=question_parse_mode, question_entities=question_entities)) async def stop_poll( self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 142491a3e..572140057 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1803,7 +1803,8 @@ async def send_poll( is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, - reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None): + reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, + reply_parameters=None,business_connection_id=None, question_parse_mode=None, question_entities=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1831,7 +1832,6 @@ async def send_poll( payload['close_date'] = close_date if is_closed is not None: payload['is_closed'] = is_closed - if disable_notification: payload['disable_notification'] = disable_notification if reply_parameters is not None: @@ -1849,6 +1849,10 @@ async def send_poll( payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if question_parse_mode: + payload['question_parse_mode'] = question_parse_mode + if question_entities: + payload['question_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(question_entities)) return await _process_request(token, method_url, params=payload) From 0e45ef5a88925de0d6d8f8803bdf3bb6f3db69cb Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 13:14:43 +0300 Subject: [PATCH 234/480] Added the parameters question_parse_mode and question_entities to the method sendPoll. u1 --- telebot/asyncio_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 572140057..7da6d7355 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -581,7 +581,7 @@ async def edit_message_live_location( if live_period: payload['live_period'] = live_period if inline_message_id: - payload['inline_message_id'] = inline_message_id\ + payload['inline_message_id'] = inline_message_id if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: From 2c9aa1d9382f6ccc92923ec6f864de8ad054f43a Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 14:13:24 +0300 Subject: [PATCH 235/480] Added the class InputPollOption and changed the type of the parameter options in the method sendPoll to Array of InputPollOption. --- telebot/__init__.py | 21 +++++++++++++++++---- telebot/apihelper.py | 22 +++++----------------- telebot/async_telebot.py | 17 ++++++++++++++--- telebot/asyncio_helper.py | 20 +++----------------- telebot/types.py | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 41 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index b76dbccce..5035689aa 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -189,6 +189,7 @@ def __init__( # logs-related if colorful_logs: try: + # noinspection PyPackageRequirements import coloredlogs coloredlogs.install(logger=logger, level=logger.level) except ImportError: @@ -1012,6 +1013,7 @@ def __notify_update(self, new_messages): def _setup_change_detector(self, path_to_watch: str): try: + # noinspection PyPackageRequirements from watchdog.observers import Observer from telebot.ext.reloader import EventHandler except ImportError: @@ -5132,7 +5134,7 @@ def create_invoice_link(self, # noinspection PyShadowingBuiltins def send_poll( - self, chat_id: Union[int, str], question: str, options: List[str], + self, chat_id: Union[int, str], question: str, options: List[types.InputPollOption], is_anonymous: Optional[bool]=None, type: Optional[str]=None, allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, @@ -5166,8 +5168,8 @@ def send_poll( :param question: Poll question, 1-300 characters :type question: :obj:`str` - :param options: A JSON-serialized list of answer options, 2-10 strings 1-100 characters each - :type options: :obj:`list` of :obj:`str` + :param options: A JSON-serialized list of 2-10 answer options + :type options: :obj:`list` of :obj:`InputPollOption` :param is_anonymous: True, if the poll needs to be anonymous, defaults to True :type is_anonymous: :obj:`bool` @@ -5265,6 +5267,17 @@ def send_poll( explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode question_parse_mode = self.parse_mode if (question_parse_mode is None) else question_parse_mode + if options and (not isinstance(options[0], types.InputPollOption)): + # show a deprecation warning + logger.warning("The parameter 'options' changed, should be List[types.InputPollOption], other types are deprecated.") + # convert options to appropriate type + if isinstance(options[0], str): + options = [types.InputPollOption(option) for option in options] + elif isinstance(options[0], types.PollOption): + options = [types.InputPollOption(option.text, text_entities=option.text_entities) for option in options] + else: + raise RuntimeError("Type of 'options' items is unknown. Options should be List[types.InputPollOption], other types are deprecated.") + return types.Message.de_json( apihelper.send_poll( self.token, chat_id, question, options, @@ -5574,7 +5587,7 @@ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types. apihelper.get_user_chat_boosts(self.token, chat_id, user_id) ) - + # noinspection PyShadowingBuiltins def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None, format: Optional[str]=None) -> bool: """ Use this method to set the thumbnail of a sticker set. diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 5a22d5f5a..6b63c0b80 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -3,6 +3,7 @@ from datetime import datetime try: + # noinspection PyPackageRequirements import ujson as json except ImportError: import json @@ -371,6 +372,7 @@ def get_chat_member_count(token, chat_id): return _make_request(token, method_url, params=payload) +# noinspection PyShadowingBuiltins def set_sticker_set_thumbnail(token, name, user_id, thumbnail, format): method_url = r'setStickerSetThumbnail' payload = {'name': name, 'user_id': user_id, 'format': format} @@ -1814,8 +1816,7 @@ def create_invoice_link(token, title, description, payload, provider_token, # noinspection PyShadowingBuiltins def send_poll( - token, chat_id, - question, options, + token, chat_id, question, options, is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, @@ -1824,7 +1825,8 @@ def send_poll( payload = { 'chat_id': str(chat_id), 'question': question, - 'options': json.dumps(_convert_poll_options(options))} + 'options': json.dumps([option.to_dict() for option in options]) + } if is_anonymous is not None: payload['is_anonymous'] = is_anonymous @@ -2002,20 +2004,6 @@ def _convert_markup(markup): return markup -def _convert_poll_options(poll_options): - if poll_options is None: - return None - elif len(poll_options) == 0: - return [] - elif isinstance(poll_options[0], str): - # Compatibility mode with previous bug when only list of string was accepted as poll_options - return poll_options - elif isinstance(poll_options[0], types.PollOption): - return [option.text for option in poll_options] - else: - return poll_options - - def convert_input_media(media): if isinstance(media, types.InputMedia): return media.convert_input_media() diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index fcbd2fc1a..23cfbdd48 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6477,7 +6477,7 @@ async def create_invoice_link(self, # noinspection PyShadowingBuiltins async def send_poll( - self, chat_id: Union[int, str], question: str, options: List[str], + self, chat_id: Union[int, str], question: str, options: List[InputPollOption], is_anonymous: Optional[bool]=None, type: Optional[str]=None, allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, @@ -6511,8 +6511,8 @@ async def send_poll( :param question: Poll question, 1-300 characters :type question: :obj:`str` - :param options: A JSON-serialized list of answer options, 2-10 strings 1-100 characters each - :type options: :obj:`list` of :obj:`str` + :param options: A JSON-serialized list of 2-10 answer options + :type options: :obj:`list` of :obj:`InputPollOption` :param is_anonymous: True, if the poll needs to be anonymous, defaults to True :type is_anonymous: :obj:`bool` @@ -6613,6 +6613,17 @@ async def send_poll( if isinstance(question, types.Poll): raise RuntimeError("The send_poll signature was changed, please see send_poll function details.") + if options and (not isinstance(options[0], types.InputPollOption)): + # show a deprecation warning + logger.warning("The parameter 'options' changed, should be List[types.InputPollOption], other types are deprecated.") + # convert options to appropriate type + if isinstance(options[0], str): + options = [types.InputPollOption(option) for option in options] + elif isinstance(options[0], types.PollOption): + options = [types.InputPollOption(option.text, text_entities=option.text_entities) for option in options] + else: + raise RuntimeError("Type of 'options' items is unknown. Options should be List[types.InputPollOption], other types are deprecated.") + return types.Message.de_json( await asyncio_helper.send_poll( self.token, chat_id, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 7da6d7355..1a56348cf 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1798,8 +1798,7 @@ async def create_invoice_link(token, title, description, payload, provider_token # noinspection PyShadowingBuiltins async def send_poll( - token, chat_id, - question, options, + token, chat_id, question, options, is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, @@ -1809,7 +1808,8 @@ async def send_poll( payload = { 'chat_id': str(chat_id), 'question': question, - 'options': json.dumps(await _convert_poll_options(options))} + 'options': json.dumps([option.to_dict() for option in options]) + } if is_anonymous is not None: payload['is_anonymous'] = is_anonymous @@ -1980,20 +1980,6 @@ async def _convert_list_json_serializable(results): return '[' + ret + ']' -async def _convert_poll_options(poll_options): - if poll_options is None: - return None - elif len(poll_options) == 0: - return [] - elif isinstance(poll_options[0], str): - # Compatibility mode with previous bug when only list of string was accepted as poll_options - return poll_options - elif isinstance(poll_options[0], types.PollOption): - return [option.text for option in poll_options] - else: - return poll_options - - async def convert_input_media(media): if isinstance(media, types.InputMedia): return media.convert_input_media() diff --git a/telebot/types.py b/telebot/types.py index 3b350dbfc..d88de77c5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6892,6 +6892,43 @@ def __init__(self, text, voter_count = 0, text_entities=None, **kwargs): # return json.dumps(self.text) +class InputPollOption(JsonSerializable): + """ + This object contains information about one answer option in a poll to send. + + Telegram Documentation: https://core.telegram.org/bots/api#inputpolloption + + :param text: Option text, 1-100 characters + :type text: :obj:`str` + + :param text_parse_mode: Optional. Mode for parsing entities in the text. See formatting options for more details. Currently, only custom emoji entities are allowed + :type text_parse_mode: :obj:`str` + + :param text_entities: Optional. A JSON-serialized list of special entities that appear in the poll option text. It can be specified instead of text_parse_mode + :type text_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :return: Instance of the class + :rtype: :class:`telebot.types.PollOption` + """ + def __init__(self, text, text_parse_mode=None, text_entities=None, **kwargs): + self.text: str = text + self.text_parse_mode: Optional[str] = text_parse_mode + self.text_entities: List[MessageEntity] = text_entities + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + json_dict = { + "text": self.text, + } + if self.text_parse_mode: + json_dict["text_parse_mode"] = self.text_parse_mode + if self.text_entities: + json_dict['text_entities'] = [entity.to_dict() for entity in self.text_entities] + return json_dict + + class Poll(JsonDeserializable): """ This object contains information about a poll. From cad5025ad517affa8731512f418df47765b1d9f1 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 14:14:50 +0300 Subject: [PATCH 236/480] Fix copy_message (not for BotAPI 7.3) --- telebot/__init__.py | 2 +- telebot/apihelper.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 5035689aa..1586fa5d4 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1891,7 +1891,7 @@ def copy_message( apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters)) + message_thread_id=message_thread_id, reply_parameters=reply_parameters)) def delete_message(self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 6b63c0b80..6d113a339 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -439,6 +439,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['disable_notification'] = disable_notification if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if reply_markup is not None: + payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout if protect_content is not None: From f75814bd5e3c6f343e4473a6525223eaa820bbf8 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 10 May 2024 14:16:22 +0300 Subject: [PATCH 237/480] Fix copy_message (not for BotAPI 7.3) u1 --- telebot/apihelper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 6d113a339..ced5ee0b3 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -440,7 +440,7 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() if reply_markup is not None: - payload['reply_markup'] = await _convert_markup(reply_markup) + payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout if protect_content is not None: From 25241c4ecef74672f9b1937192082b29181b8ecc Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 11 May 2024 01:00:28 +0300 Subject: [PATCH 238/480] Added the classes ChatBackground, BackgroundType, BackgroundFill and the field chat_background_set of type ChatBackground to the class Message, describing service messages about background changes. --- telebot/types.py | 352 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 340 insertions(+), 12 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index d88de77c5..ea208c5ef 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9,6 +9,7 @@ from abc import ABC try: + # noinspection PyPackageRequirements import ujson as json except ImportError: import json @@ -190,7 +191,7 @@ class Update(JsonDeserializable): :type edited_business_message: :class:`telebot.types.Message` :param deleted_business_messages: Optional. Service message: the chat connected to the business account was deleted - :type deleted_business_messages: :class:`telebot.types.Message` + :type deleted_business_messages: :class:`telebot.types.BusinessMessagesDeleted` :return: Instance of the class :rtype: :class:`telebot.types.Update` @@ -226,13 +227,15 @@ def de_json(cls, json_string): return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, - business_connection, business_message, edited_business_message, deleted_business_messages) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, + removed_chat_boost, chat_boost, business_connection, business_message, edited_business_message, + deleted_business_messages) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, - business_connection, business_message, edited_business_message, deleted_business_messages, **kwargs): + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, + removed_chat_boost, chat_boost, business_connection, business_message, edited_business_message, + deleted_business_messages, **kwargs): self.update_id = update_id self.message = message self.edited_message = edited_message @@ -500,7 +503,8 @@ def de_json(cls, json_string): obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, + # noinspection PyShadowingBuiltins + def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, **kwargs): self.id: int = id @@ -516,7 +520,6 @@ def __init__(self, id, is_bot, first_name, last_name=None, username=None, langua self.added_to_attachment_menu: bool = added_to_attachment_menu self.can_connect_to_business: bool = can_connect_to_business - @property def full_name(self): """ @@ -543,7 +546,6 @@ def to_dict(self): 'is_premium': self.is_premium, 'added_to_attachment_menu': self.added_to_attachment_menu, 'can_connect_to_business': self.can_connect_to_business} - class GroupChat(JsonDeserializable): @@ -1092,6 +1094,9 @@ class Message(JsonDeserializable): :param boost_added: Optional. Service message: user boosted the chat :type boost_added: :class:`telebot.types.ChatBoostAdded` + :param chat_background_set: Optional. Service message: chat background set + :type chat_background_set: :class:`telebot.types.ChatBackground` + :param forum_topic_created: Optional. Service message: forum topic created :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` @@ -1137,8 +1142,7 @@ class Message(JsonDeserializable): :param web_app_data: Optional. Service message: data sent by a Web App :type web_app_data: :class:`telebot.types.WebAppData` - :param reply_markup: Optional. Inline keyboard attached to the message. login_url buttons are represented as - ordinary url buttons. + :param reply_markup: Optional. Inline keyboard attached to the message. login_url buttons are represented as ordinary url buttons. :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` :return: Instance of the class @@ -1303,6 +1307,9 @@ def de_json(cls, json_string): content_type = 'message_auto_delete_timer_changed' if 'reply_markup' in obj: opts['reply_markup'] = InlineKeyboardMarkup.de_json(obj['reply_markup']) + if 'chat_background_set' in obj: + opts['chat_background_set'] = ChatBackground.de_json(obj['chat_background_set']) + content_type = 'chat_background_set' if 'forum_topic_created' in obj: opts['forum_topic_created'] = ForumTopicCreated.de_json(obj['forum_topic_created']) content_type = 'forum_topic_created' @@ -1451,6 +1458,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.reply_markup: Optional[InlineKeyboardMarkup] = None self.message_thread_id: Optional[int] = None self.is_topic_message: Optional[bool] = None + self.chat_background_set: Optional[ChatBackground] = None self.forum_topic_created: Optional[ForumTopicCreated] = None self.forum_topic_closed: Optional[ForumTopicClosed] = None self.forum_topic_reopened: Optional[ForumTopicReopened] = None @@ -9368,7 +9376,7 @@ def __getattr__(self, item): 'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'message_auto_delete_timer_changed', 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message', 'invoice', 'successful_payment', 'users_shared', 'chat_shared', 'connected_website', 'write_access_allowed', 'passport_data', - 'proximity_alert_triggered', 'forum_topic_created', 'forum_topic_edited', 'forum_topic_closed', + 'proximity_alert_triggered', 'chat_background_set', 'forum_topic_created', 'forum_topic_edited', 'forum_topic_closed', 'forum_topic_reopened', 'general_forum_topic_hidden', 'general_forum_topic_unhidden', 'giveaway_created', 'giveaway', 'giveaway_winners', 'giveaway_completed', 'video_chat_scheduled', 'video_chat_started', 'video_chat_ended', 'video_chat_participants_invited', 'web_app_data', 'reply_markup' @@ -9668,4 +9676,324 @@ def de_json(cls, json_string): def __init__(self, day, month, year=None, **kwargs): self.day: int = day self.month: int = month - self.year: Optional[int] = year \ No newline at end of file + self.year: Optional[int] = year + + +class BackgroundFill(ABC, JsonDeserializable): + """ + This object describes the way a background is filled based on the selected colors. Currently, it can be one of + BackgroundFillSolid + BackgroundFillGradient + BackgroundFillFreeformGradient + + Telegram documentation: https://core.telegram.org/bots/api#backgroundfill + + :return: Instance of the class + :rtype: :class:`BackgroundFillSolid` or :class:`BackgroundFillGradient` or :class:`BackgroundFillFreeformGradient` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if obj["type"] == "solid": + return BackgroundFillSolid.de_json(obj) + elif obj["type"] == "gradient": + return BackgroundFillGradient.de_json(obj) + elif obj["type"] == "freeform_gradient": + return BackgroundFillFreeformGradient.de_json(obj) + return None + + +# noinspection PyShadowingBuiltins +class BackgroundFillSolid(BackgroundFill): + """ + The background is filled using the selected color. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundfillsolid + + :param type: Type of the background fill, always “solid” + :type type: :obj:`str` + + :param color: The color of the background fill in the RGB24 format + :type color: :class:`int` + + :return: Instance of the class + :rtype: :class:`BackgroundFillSolid` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, type, color, **kwargs): + self.type: str = type + self.color: int = color + + +# noinspection PyShadowingBuiltins +class BackgroundFillGradient(BackgroundFill): + """ + The background is a gradient fill. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundfillgradient + + :param type: Type of the background fill, always “gradient” + :type type: :obj:`str` + + :param top_color: Top color of the gradient in the RGB24 format + :type top_color: :class:`int` + + :param bottom_color: Bottom color of the gradient in the RGB24 format + :type bottom_color: :class:`int` + + :param rotation_angle: Clockwise rotation angle of the background fill in degrees; 0-359 + :type rotation_angle: :class:`int` + + :return: Instance of the class + :rtype: :class:`BackgroundFillGradient` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, type, top_color, bottom_color, rotation_angle, **kwargs): + self.type: str = type + self.top_color: int = top_color + self.bottom_color: int = bottom_color + self.rotation_angle: int = rotation_angle + + +# noinspection PyShadowingBuiltins +class BackgroundFillFreeformGradient(BackgroundFill): + """ + The background is a freeform gradient that rotates after every message in the chat. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundfillfreeformgradient + + :param type: Type of the background fill, always “freeform_gradient” + :type type: :obj:`str` + + :param colors: A list of the 3 or 4 base colors that are used to generate the freeform gradient in the RGB24 format + :type colors: :obj:`list` of :class:`int` + + :return: Instance of the class + :rtype: :class:`BackgroundFillFreeformGradient` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, type, colors, **kwargs): + self.type: str = type + self.colors: List[int] = colors + + +class BackgroundType(ABC, JsonDeserializable): + """ + This object describes the type of a background. Currently, it can be one of + BackgroundTypeFill + BackgroundTypeWallpaper + BackgroundTypePattern + BackgroundTypeChatTheme + + Telegram documentation: https://core.telegram.org/bots/api#backgroundtype + + :return: Instance of the class + :rtype: :class:`BackgroundTypeFill` or :class:`BackgroundTypeWallpaper` or :class:`BackgroundTypePattern` or :class:`BackgroundTypeChatTheme` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if obj["type"] == "fill": + return BackgroundTypeFill.de_json(obj) + elif obj["type"] == "wallpaper": + return BackgroundTypeWallpaper.de_json(obj) + elif obj["type"] == "pattern": + return BackgroundTypePattern.de_json(obj) + elif obj["type"] == "chat_theme": + return BackgroundTypeChatTheme.de_json(obj) + return None + + +# noinspection PyShadowingBuiltins +class BackgroundTypeFill(BackgroundFill): + """ + The background is automatically filled based on the selected colors. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundtypefill + + :param type: Type of the background, always “fill” + :type type: :obj:`str` + + :param fill: The background fill + :type fill: :class:`BackgroundFill` + + :param dark_theme_dimming: Dimming of the background in dark themes, as a percentage; 0-100 + :type dark_theme_dimming: :obj:`int` + + :return: Instance of the class + :rtype: :class:`BackgroundTypeFill` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['fill'] = BackgroundFill.de_json(obj['fill']) + return cls(**obj) + + def __init__(self, type, fill, dark_theme_dimming, **kwargs): + self.type: str = type + self.fill: BackgroundFill = fill + self.dark_theme_dimming: int = dark_theme_dimming + + +# noinspection PyShadowingBuiltins +class BackgroundTypeWallpaper(BackgroundFill): + """ + The background is a wallpaper in the JPEG format. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundtypewallpaper + + :param type: Type of the background, always “wallpaper” + :type type: :obj:`str` + + :param document: Document with the wallpaper + :type document: :class:`Document` + + :param dark_theme_dimming: Dimming of the background in dark themes, as a percentage; 0-100 + :type dark_theme_dimming: :obj:`int` + + :param is_blurred: Optional. True, if the wallpaper is downscaled to fit in a 450x450 square and then box-blurred with radius 12 + :type is_blurred: :obj:`bool` + + :param is_moving: Optional. True, if the background moves slightly when the device is tilted + :type is_moving: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`BackgroundTypeWallpaper` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['document'] = Document.de_json(obj['document']) + obj['fill'] = BackgroundFill.de_json(obj['fill']) + return cls(**obj) + + def __init__(self, type, document, dark_theme_dimming, is_blurred=None, is_moving=None, **kwargs): + self.type: str = type + self.document: Document = document + self.dark_theme_dimming: int = dark_theme_dimming + self.is_blurred: Optional[bool] = is_blurred + self.is_moving: Optional[bool] = is_moving + + +# noinspection PyShadowingBuiltins +class BackgroundTypePattern(BackgroundFill): + """ + The background is a wallpaper in the JPEG format. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundtypepattern + + :param type: Type of the background, always “pattern” + :type type: :obj:`str` + + :param document: Document with the pattern + :type document: :class:`Document` + + :param fill: The background fill that is combined with the pattern + :type fill: :class:`BackgroundFill` + + :param intensity: Intensity of the pattern when it is shown above the filled background; 0-100 + :type intensity: :obj:`int` + + :param is_inverted: Optional. True, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only + :type is_inverted: :obj:`bool` + + :param is_moving: Optional. True, if the background moves slightly when the device is tilted + :type is_moving: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`BackgroundTypePattern` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['document'] = Document.de_json(obj['document']) + return cls(**obj) + + def __init__(self, type, document, fill, intensity, is_inverted=None, is_moving=None, **kwargs): + self.type: str = type + self.document: Document = document + self.fill: BackgroundFill = fill + self.intensity: int = intensity + self.is_inverted: Optional[bool] = is_inverted + self.is_moving: Optional[bool] = is_moving + + +# noinspection PyShadowingBuiltins +class BackgroundTypeChatTheme(BackgroundFill): + """ + The background is taken directly from a built-in chat theme. + + Telegram documentation: https://core.telegram.org/bots/api#backgroundtypechattheme + + :param type: Type of the background, always “chat_theme” + :type type: :obj:`str` + + :param theme_name: Intensity of the pattern when it is shown above the filled background; 0-100 + :type theme_name: :obj:`str` + + :return: Instance of the class + :rtype: :class:`BackgroundTypeChatTheme` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + def __init__(self, type, theme_name, **kwargs): + self.type: str = type + self.theme_name: str = theme_name + + +# noinspection PyShadowingBuiltins +class ChatBackground(JsonDeserializable): + """ + This object represents a chat background. + + Telegram documentation: https://core.telegram.org/bots/api#chatbackground + + :param type: Type of the background + :type type: :class:`BackgroundType` + + :return: Instance of the class + :rtype: :class:`ChatBackground` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['type'] = BackgroundType.de_json(obj['type']) + return cls(**obj) + + def __init__(self, type, **kwargs): + self.type: BackgroundType = type From 9a3d0488f3dc0c52e58ccac5de09ba8fd0e3bb0b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 11 May 2024 01:09:42 +0300 Subject: [PATCH 239/480] Suppress some warnings (not for BotAPI 7.3) --- telebot/types.py | 78 +++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index ea208c5ef..3c0edfe39 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -548,6 +548,7 @@ def to_dict(self): 'can_connect_to_business': self.can_connect_to_business} +# noinspection PyShadowingBuiltins class GroupChat(JsonDeserializable): """ :meta private: @@ -563,6 +564,7 @@ def __init__(self, id, title, **kwargs): self.title: str = title +# noinspection PyShadowingBuiltins class Chat(JsonDeserializable): """ This object represents a chat. @@ -1584,6 +1586,7 @@ def user_shared(self): return self.users_shared +# noinspection PyShadowingBuiltins class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): """ This object represents one special entity in a text message. For example, hashtags, usernames, URLs, etc. @@ -2461,20 +2464,20 @@ def to_json(self): return json.dumps(json_dict) +# noinspection PyShadowingBuiltins class KeyboardButtonPollType(Dictionaryable): """ This object represents type of a poll, which is allowed to be created and sent when the corresponding button is pressed. Telegram Documentation: https://core.telegram.org/bots/api#keyboardbuttonpolltype - :param type: Optional. If quiz is passed, the user will be allowed to create only polls in the quiz mode. If regular is - passed, only regular polls will be allowed. Otherwise, the user will be allowed to create a poll of any type. + :param type: Optional. If quiz is passed, the user will be allowed to create only polls in the quiz mode. If regular is passed, only regular polls will be allowed. Otherwise, the user will be allowed to create a poll of any type. :type type: :obj:`str` :return: Instance of the class :rtype: :class:`telebot.types.KeyboardButtonPollType` """ - def __init__(self, type=''): + def __init__(self, type=None): self.type: str = type def to_dict(self): @@ -2991,6 +2994,7 @@ def to_dict(self): return json_dict +# noinspection PyShadowingBuiltins class CallbackQuery(JsonDeserializable): """ This object represents an incoming callback query from a callback button in an inline keyboard. If the button that originated the query was attached to a message sent by the bot, the field message will be present. If the button was attached to a message sent via the bot (in inline mode), the field inline_message_id will be present. Exactly one of the fields data or game_short_name will be present. @@ -3585,6 +3589,7 @@ def to_dict(self): # BotCommandScopes +# noinspection PyShadowingBuiltins class BotCommandScope(ABC, JsonSerializable): """ This object represents the scope to which bot commands are applied. Currently, the following 7 scopes are supported: @@ -3790,6 +3795,7 @@ def __init__(self, chat_id=None, user_id=None): # InlineQuery +# noinspection PyShadowingBuiltins class InlineQuery(JsonDeserializable): """ This object represents an incoming inline query. When the user sends an empty query, your bot could return some default or trending results. @@ -4316,7 +4322,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultArticle(InlineQueryResultBase): """ Represents a link to an article or web page. @@ -4401,7 +4407,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultPhoto(InlineQueryResultBase): """ Represents a link to a photo. By default, this photo will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the photo. @@ -4481,7 +4487,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultGif(InlineQueryResultBase): """ Represents a link to an animated GIF file. By default, this animated GIF file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4574,7 +4580,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultMpeg4Gif(InlineQueryResultBase): """ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). By default, this animated MPEG-4 file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4667,7 +4673,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultVideo(InlineQueryResultBase): """ Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video. @@ -4759,7 +4765,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultAudio(InlineQueryResultBase): """ Represents a link to an MP3 audio file. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio. @@ -4824,7 +4830,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultVoice(InlineQueryResultBase): """ Represents a link to a voice recording in an .OGG container encoded with OPUS. By default, this voice recording will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the the voice message. @@ -4882,7 +4888,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultDocument(InlineQueryResultBase): """ Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. Currently, only .PDF and .ZIP files can be sent using this method. @@ -4979,7 +4985,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultLocation(InlineQueryResultBase): """ Represents a location on a map. By default, the location will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the location. @@ -5081,7 +5087,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultVenue(InlineQueryResultBase): """ Represents a venue. By default, the venue will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the venue. @@ -5190,7 +5196,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultContact(InlineQueryResultBase): """ Represents a contact with a phone number. By default, this contact will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the contact. @@ -5278,7 +5284,7 @@ def to_dict(self): return json_dict -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultGame(InlineQueryResultBase): """ Represents a Game. @@ -5347,7 +5353,7 @@ def to_json(self): return json.dumps(json_dict) -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedPhoto(InlineQueryResultCachedBase): """ Represents a link to a photo stored on the Telegram servers. By default, this photo will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the photo. @@ -5406,7 +5412,7 @@ def __init__(self, id, photo_file_id, title=None, description=None, self.payload_dic['photo_file_id'] = photo_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedGif(InlineQueryResultCachedBase): """ Represents a link to an animated GIF file stored on the Telegram servers. By default, this animated GIF file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with specified content instead of the animation. @@ -5461,7 +5467,7 @@ def __init__(self, id, gif_file_id, title=None, description=None, self.payload_dic['gif_file_id'] = gif_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedMpeg4Gif(InlineQueryResultCachedBase): """ Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) stored on the Telegram servers. By default, this animated MPEG-4 file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -5516,7 +5522,7 @@ def __init__(self, id, mpeg4_file_id, title=None, description=None, self.payload_dic['mpeg4_file_id'] = mpeg4_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedSticker(InlineQueryResultCachedBase): """ Represents a link to a sticker stored on the Telegram servers. By default, this sticker will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the sticker. @@ -5551,7 +5557,7 @@ def __init__(self, id, sticker_file_id, reply_markup=None, input_message_content self.payload_dic['sticker_file_id'] = sticker_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedDocument(InlineQueryResultCachedBase): """ Represents a link to a file stored on the Telegram servers. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. @@ -5610,7 +5616,7 @@ def __init__(self, id, document_file_id, title, description=None, self.payload_dic['document_file_id'] = document_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedVideo(InlineQueryResultCachedBase): """ Represents a link to a video file stored on the Telegram servers. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video. @@ -5670,7 +5676,7 @@ def __init__(self, id, video_file_id, title, description=None, self.payload_dic['video_file_id'] = video_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedVoice(InlineQueryResultCachedBase): """ Represents a link to a voice message stored on the Telegram servers. By default, this voice message will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the voice message. @@ -5724,7 +5730,7 @@ def __init__(self, id, voice_file_id, title, caption=None, caption_entities = No self.payload_dic['voice_file_id'] = voice_file_id -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedAudio(InlineQueryResultCachedBase): """ Represents a link to an MP3 audio file stored on the Telegram servers. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio. @@ -6092,7 +6098,7 @@ def __init__(self, name=None, phone_number=None, email=None, shipping_address=No self.shipping_address: ShippingAddress = shipping_address -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class ShippingOption(JsonSerializable): """ This object represents one shipping option. @@ -6187,6 +6193,7 @@ def __init__(self, currency, total_amount, invoice_payload, shipping_option_id=N self.provider_payment_charge_id: str = provider_payment_charge_id +# noinspection PyShadowingBuiltins class ShippingQuery(JsonDeserializable): """ This object contains information about an incoming shipping query. @@ -6223,6 +6230,7 @@ def __init__(self, id, from_user, invoice_payload, shipping_address, **kwargs): self.shipping_address: ShippingAddress = shipping_address +# noinspection PyShadowingBuiltins class PreCheckoutQuery(JsonDeserializable): """ This object contains information about an incoming pre-checkout query. @@ -6350,6 +6358,7 @@ def is_video(self): return False +# noinspection PyShadowingBuiltins class Sticker(JsonDeserializable): """ This object represents a sticker. @@ -6494,6 +6503,7 @@ def to_dict(self): # InputMedia +# noinspection PyShadowingBuiltins class InputMedia(Dictionaryable, JsonSerializable): """ This object represents the content of a media message to be sent. It should be one of @@ -7398,12 +7408,12 @@ class MenuButton(JsonDeserializable, JsonSerializable, Dictionaryable): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - map = { + types = { 'commands': MenuButtonCommands, 'web_app': MenuButtonWebApp, 'default': MenuButtonDefault } - return map[obj['type']](**obj) + return types[obj['type']](**obj) def to_json(self): """ @@ -7416,8 +7426,9 @@ def to_dict(self): :meta private: """ raise NotImplementedError - + +# noinspection PyUnusedLocal class MenuButtonCommands(MenuButton): """ Represents a menu button, which opens the bot's list of commands. @@ -7441,6 +7452,7 @@ def to_json(self): return json.dumps(self.to_dict()) +# noinspection PyUnusedLocal class MenuButtonWebApp(MenuButton): """ Represents a menu button, which launches a Web App. @@ -7472,7 +7484,8 @@ def to_dict(self): def to_json(self): return json.dumps(self.to_dict()) - + +# noinspection PyUnusedLocal class MenuButtonDefault(MenuButton): """ Describes that no specific value for the menu button was set. @@ -7953,6 +7966,7 @@ def __init__(self, short_description: str, **kwargs) -> None: self.short_description: str = short_description +# noinspection PyShadowingBuiltins class InputSticker(Dictionaryable, JsonSerializable): """ This object describes a sticker to be added to a sticker set. @@ -8187,6 +8201,7 @@ def __init__(self, chat: Chat, id: int, **kwargs) -> None: # base class +# noinspection PyShadowingBuiltins class ReactionType(JsonDeserializable, Dictionaryable, JsonSerializable): """ This object represents a reaction type. @@ -8371,8 +8386,9 @@ def __init__(self, chat: Chat, message_id: int, date: int, reactions: List[React self.message_id: int = message_id self.date: int = date self.reactions: List[ReactionCount] = reactions - + +# noinspection PyShadowingBuiltins class ReactionCount(JsonDeserializable): """ This object represents a reaction added to a message along with the number of times it was added. @@ -8563,7 +8579,7 @@ def __init__( self.venue: Optional[Venue] = venue -# noinspection PyUnresolvedReferences +# noinspection PyUnresolvedReferences,PyShadowingBuiltins class MessageOrigin(JsonDeserializable): """ This object describes the origin of a message. @@ -9409,7 +9425,7 @@ def __init__(self, boost_count, **kwargs): self.boost_count: int = boost_count - +# noinspection PyShadowingBuiltins class BusinessConnection(JsonDeserializable): """ This object describes the connection of the bot with a business account. From 3532812e0ed6d44675a4f16c4e2efd3c57b3dd1d Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 11 May 2024 15:43:05 +0300 Subject: [PATCH 240/480] Split out the class ChatFullInfo from the class Chat and changed the return type of the method getChat to ChatFullInfo. Added the field max_reaction_count to the class ChatFullInfo. --- telebot/__init__.py | 6 +-- telebot/apihelper.py | 4 +- telebot/async_telebot.py | 6 +-- telebot/types.py | 87 ++++++++++++++++++---------------------- 4 files changed, 48 insertions(+), 55 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 1586fa5d4..2d327ab5a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1493,7 +1493,7 @@ def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, ) - def get_chat(self, chat_id: Union[int, str]) -> types.Chat: + def get_chat(self, chat_id: Union[int, str]) -> types.ChatFullInfo: """ Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success. @@ -1504,9 +1504,9 @@ def get_chat(self, chat_id: Union[int, str]) -> types.Chat: :type chat_id: :obj:`int` or :obj:`str` :return: Chat information - :rtype: :class:`telebot.types.Chat` + :rtype: :class:`telebot.types.ChatFullInfo` """ - return types.Chat.de_json( + return types.ChatFullInfo.de_json( apihelper.get_chat(self.token, chat_id) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index ced5ee0b3..82a1e31e6 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1527,10 +1527,10 @@ def send_invoice( :param provider_data: A JSON-serialized data about the invoice, which will be shared with the payment provider. A detailed description of required fields should be provided by the payment provider. :param timeout: :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency - :param suggested_tip_amounts: A JSON-serialized array of suggested amounts of tips in the smallest units of the currency. - At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount. + :param suggested_tip_amounts: A JSON-serialized array of suggested amounts of tips in the smallest units of the currency. At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount. :param protect_content: Protects the contents of the sent message from forwarding and saving :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + :param reply_parameters: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. :return: """ method_url = r'sendInvoice' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 23cfbdd48..1b6c09413 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2889,7 +2889,7 @@ async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None result = await asyncio_helper.get_user_profile_photos(self.token, user_id, offset, limit) return types.UserProfilePhotos.de_json(result) - async def get_chat(self, chat_id: Union[int, str]) -> types.Chat: + async def get_chat(self, chat_id: Union[int, str]) -> types.ChatFullInfo: """ Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). Returns a Chat object on success. @@ -2900,10 +2900,10 @@ async def get_chat(self, chat_id: Union[int, str]) -> types.Chat: :type chat_id: :obj:`int` or :obj:`str` :return: Chat information - :rtype: :class:`telebot.types.Chat` + :rtype: :class:`telebot.types.ChatFullInfo` """ result = await asyncio_helper.get_chat(self.token, chat_id) - return types.Chat.de_json(result) + return types.ChatFullInfo.de_json(result) async def leave_chat(self, chat_id: Union[int, str]) -> bool: """ diff --git a/telebot/types.py b/telebot/types.py index 3c0edfe39..cfbe447fd 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -565,7 +565,7 @@ def __init__(self, id, title, **kwargs): # noinspection PyShadowingBuiltins -class Chat(JsonDeserializable): +class ChatFullInfo(JsonDeserializable): """ This object represents a chat. @@ -594,11 +594,13 @@ class Chat(JsonDeserializable): :param is_forum: Optional. True, if the supergroup chat is a forum (has topics enabled) :type is_forum: :obj:`bool` + :param max_reaction_count: Optional. The maximum number of reactions that can be set on a message in the chat + :type max_reaction_count: :obj:`int` + :param photo: Optional. Chat photo. Returned only in getChat. :type photo: :class:`telebot.types.ChatPhoto` - :param active_usernames: Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. - Returned only in getChat. + :param active_usernames: Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. Returned only in getChat. :type active_usernames: :obj:`list` of :obj:`str` :param birthdate: Optional. Birthdate of the other party in a private chat. Returned only in getChat. @@ -616,100 +618,80 @@ class Chat(JsonDeserializable): :param personal_chat: Optional. For private chats, the personal channel of the user. Returned only in getChat. :type personal_chat: :class:`telebot.types.Chat` - :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels. - Returned only in getChat. + :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels. Returned only in getChat. :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType` :param accent_color_id: Optional. Optional. Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See accent colors for more details. Returned only in getChat. Always returned in getChat. :type accent_color_id: :obj:`int` - :param background_custom_emoji_id: Optional. Custom emoji identifier of emoji chosen by the chat for the reply header - and link preview background. Returned only in getChat. + :param background_custom_emoji_id: Optional. Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. Returned only in getChat. :type background_custom_emoji_id: :obj:`str` - :param profile_accent_color_id: Optional. Identifier of the accent color for the chat's profile background. - See profile accent colors for more details. Returned only in getChat. + :param profile_accent_color_id: Optional. Identifier of the accent color for the chat's profile background. See profile accent colors for more details. Returned only in getChat. :type profile_accent_color_id: :obj:`int` - :param profile_background_custom_emoji_id: Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. - Returned only in getChat. + :param profile_background_custom_emoji_id: Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. Returned only in getChat. :type profile_background_custom_emoji_id: :obj:`str` - :param emoji_status_custom_emoji_id: Optional. Custom emoji identifier of emoji status of the other party in a private chat. - Returned only in getChat. + :param emoji_status_custom_emoji_id: Optional. Custom emoji identifier of emoji status of the other party in a private chat. Returned only in getChat. :type emoji_status_custom_emoji_id: :obj:`str` - :param emoji_status_expiration_date: Optional. Expiration date of the emoji status of the other party in a private chat, - if any. Returned only in getChat. + :param emoji_status_expiration_date: Optional. Expiration date of the emoji status of the other party in a private chat, if any. Returned only in getChat. :type emoji_status_expiration_date: :obj:`int` :param bio: Optional. Bio of the other party in a private chat. Returned only in getChat. :type bio: :obj:`str` - :param has_private_forwards: Optional. :obj:`bool`, if privacy settings of the other party in the private chat - allows to use tg://user?id= links only in chats with the user. Returned only in getChat. + :param has_private_forwards: Optional. :obj:`bool`, if privacy settings of the other party in the private chat allows to use tg://user?id= links only in chats with the user. Returned only in getChat. :type has_private_forwards: :obj:`bool` - :param has_restricted_voice_and_video_messages: Optional. True, if the privacy settings of the other party restrict sending voice and video note messages - in the private chat. Returned only in getChat. + :param has_restricted_voice_and_video_messages: Optional. True, if the privacy settings of the other party restrict sending voice and video note messages in the private chat. Returned only in getChat. :type :obj:`bool` - :param join_to_send_messages: Optional. :obj:`bool`, if users need to join the supergroup before they can send - messages. Returned only in getChat. + :param join_to_send_messages: Optional. :obj:`bool`, if users need to join the supergroup before they can send messages. Returned only in getChat. :type join_to_send_messages: :obj:`bool` - :param join_by_request: Optional. :obj:`bool`, if all users directly joining the supergroup need to be approved - by supergroup administrators. Returned only in getChat. + :param join_by_request: Optional. :obj:`bool`, if all users directly joining the supergroup need to be approved by supergroup administrators. Returned only in getChat. :type join_by_request: :obj:`bool` :param description: Optional. Description, for groups, supergroups and channel chats. Returned only in getChat. :type description: :obj:`str` - :param invite_link: Optional. Primary invite link, for groups, supergroups and channel chats. Returned only in - getChat. + :param invite_link: Optional. Primary invite link, for groups, supergroups and channel chats. Returned only in getChat. :type invite_link: :obj:`str` :param pinned_message: Optional. The most recent pinned message (by sending date). Returned only in getChat. :type pinned_message: :class:`telebot.types.Message` - :param permissions: Optional. Default chat member permissions, for groups and supergroups. Returned only in - getChat. + :param permissions: Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. :type permissions: :class:`telebot.types.ChatPermissions` - :param slow_mode_delay: Optional. For supergroups, the minimum allowed delay between consecutive messages sent - by each unpriviledged user; in seconds. Returned only in getChat. + :param slow_mode_delay: Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unpriviledged user; in seconds. Returned only in getChat. :type slow_mode_delay: :obj:`int` - :param unrestrict_boost_count: Optional. For supergroups, the minimum number of boosts that a non-administrator - user needs to add in order to ignore slow mode and chat permissions. Returned only in getChat. + :param unrestrict_boost_count: Optional. For supergroups, the minimum number of boosts that a non-administrator user needs to add in order to ignore slow mode and chat permissions. Returned only in getChat. :type unrestrict_boost_count: :obj:`int` - :param message_auto_delete_time: Optional. The time after which all messages sent to the chat will be - automatically deleted; in seconds. Returned only in getChat. + :param message_auto_delete_time: Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in getChat. :type message_auto_delete_time: :obj:`int` - :param has_aggressive_anti_spam_enabled: Optional. :obj:`bool`, if the chat has enabled aggressive anti-spam - protection. Returned only in getChat. + :param has_aggressive_anti_spam_enabled: Optional. :obj:`bool`, if the chat has enabled aggressive anti-spam protection. Returned only in getChat. :type has_aggressive_anti_spam_enabled: :obj:`bool` - :param has_hidden_members: Optional. :obj:`bool`, if the chat has enabled hidden members. Returned only in - getChat. + :param has_hidden_members: Optional. :obj:`bool`, if the chat has enabled hidden members. Returned only in getChat. :type has_hidden_members: :obj:`bool` - :param has_protected_content: Optional. :obj:`bool`, if messages from the chat can't be forwarded to other - chats. Returned only in getChat. + :param has_protected_content: Optional. :obj:`bool`, if messages from the chat can't be forwarded to other chats. Returned only in getChat. :type has_protected_content: :obj:`bool` - :param has_visible_history: Optional. True, if new chat members will have access to old messages; - available only to chat administrators. Returned only in getChat. + :param has_visible_history: Optional. True, if new chat members will have access to old messages; available only to chat administrators. Returned only in getChat. :type has_visible_history: :obj:`bool` :param sticker_set_name: Optional. For supergroups, name of group sticker set. Returned only in getChat. :type sticker_set_name: :obj:`str` - :param can_set_sticker_set: Optional. :obj:`bool`, if the bot can change the group sticker set. Returned only in - getChat. + :param can_set_sticker_set: Optional. :obj:`bool`, if the bot can change the group sticker set. Returned only in getChat. :type can_set_sticker_set: :obj:`bool` :param custom_emoji_sticker_set_name: Optional. For supergroups, the name of the group's custom emoji sticker set. @@ -722,12 +704,11 @@ class Chat(JsonDeserializable): signed 64 bit integer or double-precision float type are safe for storing this identifier. Returned only in getChat. :type linked_chat_id: :obj:`int` - :param location: Optional. For supergroups, the location to which the supergroup is connected. Returned only in - getChat. + :param location: Optional. For supergroups, the location to which the supergroup is connected. Returned only in getChat. :type location: :class:`telebot.types.ChatLocation` :return: Instance of the class - :rtype: :class:`telebot.types.Chat` + :rtype: :class:`telebot.types.ChatFullInfo` """ @classmethod def de_json(cls, json_string): @@ -762,7 +743,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, message_auto_delete_time=None, has_protected_content=None, sticker_set_name=None, can_set_sticker_set=None, linked_chat_id=None, location=None, join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, - is_forum=None, active_usernames=None, emoji_status_custom_emoji_id=None, + is_forum=None, max_reaction_count=None, active_usernames=None, emoji_status_custom_emoji_id=None, has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, profile_background_custom_emoji_id=None, has_visible_history=None, @@ -775,6 +756,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.first_name: str = first_name self.last_name: str = last_name self.is_forum: bool = is_forum + self.max_reaction_count: int = max_reaction_count self.photo: ChatPhoto = photo self.bio: str = bio self.join_to_send_messages: bool = join_to_send_messages @@ -812,6 +794,17 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.birthdate: Birthdate = birthdate +class Chat(ChatFullInfo): + """ + In BotAPI 7.3 Chat was reduced and full info moved to ChatFullInfo: + "Split out the class ChatFullInfo from the class Chat and changed the return type of the method getChat to ChatFullInfo." + + https://core.telegram.org/bots/api#chatfullinfo + + Currently Chat is left as full copy of ChatFullInfo for compatibility. + """ + pass + class MessageID(JsonDeserializable): """ From 852b096ecd57785092dadf9a41ca9314a6ea988c Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 15 May 2024 10:41:13 +0300 Subject: [PATCH 241/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f11bf8f9..73880b554 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.2! +##

Supported Bot API version: 7.3!

Official documentation

Official ru documentation

From e2aa7a7132fc47da541c97c5fa82811eec54c8b4 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 15 May 2024 14:21:50 +0300 Subject: [PATCH 242/480] Bugfix in typing --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/async_telebot.py | 2 +- telebot/version.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index bb40d90ab..7e46d02c3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.18.0' +release = '4.18.1' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 6666fee8b..7eae1722e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.18.0" +version = "4.18.1" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 1b6c09413..992625641 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6477,7 +6477,7 @@ async def create_invoice_link(self, # noinspection PyShadowingBuiltins async def send_poll( - self, chat_id: Union[int, str], question: str, options: List[InputPollOption], + self, chat_id: Union[int, str], question: str, options: List[types.InputPollOption], is_anonymous: Optional[bool]=None, type: Optional[str]=None, allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, diff --git a/telebot/version.py b/telebot/version.py index 4ee703d3d..830950124 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.18.0' +__version__ = '4.18.1' From d4f7f8301035979eb88eafb70fdedffc67553cea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 05:41:29 +0000 Subject: [PATCH 243/480] --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 32cb38aa1..09014549b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest -requests==2.31.0 +requests==2.32.0 wheel==0.38.1 aiohttp==3.9.4 From 5f7a8626b02f49b2aae371ad9b2d5dab53cf6062 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 16:42:29 +0400 Subject: [PATCH 244/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73880b554..770186d5c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.3! +##

Supported Bot API version: 7.4!

Official documentation

Official ru documentation

From 6a7c34f6b6b65aae98e9e7110f50208eb6dec81b Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 16:59:10 +0400 Subject: [PATCH 245/480] Added the method refundStarPayment. --- telebot/__init__.py | 16 ++++++++++++++++ telebot/apihelper.py | 5 +++++ telebot/async_telebot.py | 17 +++++++++++++++++ telebot/asyncio_helper.py | 6 ++++++ 4 files changed, 44 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 2d327ab5a..6c1853e16 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5375,7 +5375,23 @@ def answer_pre_checkout_query( """ return apihelper.answer_pre_checkout_query( self.token, pre_checkout_query_id, ok, error_message=error_message) + + def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: + """ + Refunds a successful payment in Telegram Stars. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#refundstarpayment + + :param user_id: Identifier of the user whose payment will be refunded + :type user_id: :obj:`int` + :param telegram_payment_charge_id: Telegram payment identifier + :type telegram_payment_charge_id: :obj:`str` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + return apihelper.refund_star_payment(self.token, user_id, telegram_payment_charge_id) def edit_message_caption( self, caption: str, chat_id: Optional[Union[int, str]]=None, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 82a1e31e6..0ef0d2211 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1616,6 +1616,11 @@ def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_message=No payload['error_message'] = error_message return _make_request(token, method_url, params=payload) +def refund_star_payment(token, user_id, telegram_payment_charge_id): + method_url = 'refundStarPayment' + payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id} + return _make_request(token, method_url, params=payload, method='post') + def unpin_all_general_forum_topic_messages(token, chat_id): method_url = 'unpinAllGeneralForumTopicMessages' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 992625641..f5eda28c0 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6711,6 +6711,23 @@ async def answer_pre_checkout_query( :rtype: :obj:`bool` """ return await asyncio_helper.answer_pre_checkout_query(self.token, pre_checkout_query_id, ok, error_message) + + async def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: + """ + Refunds a successful payment in Telegram Stars. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#refundstarpayment + + :param user_id: Identifier of the user whose payment will be refunded + :type user_id: :obj:`int` + + :param telegram_payment_charge_id: Telegram payment identifier + :type telegram_payment_charge_id: :obj:`str` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + return await asyncio_helper.refund_star_payment(self.token, user_id, telegram_payment_charge_id) async def edit_message_caption( self, caption: str, chat_id: Optional[Union[int, str]]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 1a56348cf..d63ec5773 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1601,6 +1601,12 @@ async def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_mess return await _process_request(token, method_url, params=payload) +async def refund_star_payment(token, user_id, telegram_payment_charge_id): + method_url = 'refundStarPayment' + payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id} + return await _process_request(token, method_url, params=payload, method='post') + + async def unpin_all_general_forum_topic_messages(token, chat_id): method_url = 'unpinAllGeneralForumTopicMessages' payload = {'chat_id': chat_id} From 83e2c440a341a9640426889eeaa5e0cb7edf7890 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 17:03:11 +0400 Subject: [PATCH 246/480] Added the field effect_id to the class Message. --- telebot/types.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index cfbe447fd..f5380e084 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -951,6 +951,9 @@ class Message(JsonDeserializable): if it is a text message and link preview options were changed :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param effect_id: Optional. Unique identifier of the message effect added to the message + :type effect_id: :obj:`str` + :param animation: Optional. Message is an animation, information about the animation. For backward compatibility, when this field is set, the document field will also be set :type animation: :class:`telebot.types.Animation` @@ -1370,6 +1373,8 @@ def de_json(cls, json_string): opts['business_connection_id'] = obj['business_connection_id'] if 'is_from_offline' in obj: opts['is_from_offline'] = obj['is_from_offline'] + if 'effect_id' in obj: + opts['effect_id'] = obj['effect_id'] @@ -1479,6 +1484,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.sender_business_bot: Optional[User] = None self.business_connection_id: Optional[str] = None self.is_from_offline: Optional[bool] = None + self.effect_id: Optional[str] = None for key in options: setattr(self, key, options[key]) From 249ef2e57f64d594e51c32bf7755257ff0ae9a50 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 17:28:00 +0400 Subject: [PATCH 247/480] Added the parameter message_effect_id to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendPoll, sendDice, sendInvoice, sendGame, and sendMediaGroup. --- telebot/__init__.py | 149 ++++++++++++++++++++++++++++++--------- telebot/async_telebot.py | 139 +++++++++++++++++++++++++++--------- 2 files changed, 220 insertions(+), 68 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 6c1853e16..ffc3b485b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1649,7 +1649,8 @@ def send_message( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, link_preview_options : Optional[types.LinkPreviewOptions]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send text messages. @@ -1705,6 +1706,9 @@ def send_message( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1752,7 +1756,8 @@ def send_message( self.token, chat_id, text, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, entities=entities, protect_content=protect_content, message_thread_id=message_thread_id, - reply_parameters=reply_parameters, link_preview_options=link_preview_options, business_connection_id=business_connection_id)) + reply_parameters=reply_parameters, link_preview_options=link_preview_options, business_connection_id=business_connection_id, + message_effect_id=message_effect_id)) def forward_message( @@ -2040,7 +2045,8 @@ def send_dice( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -2082,6 +2088,9 @@ def send_dice( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2110,7 +2119,8 @@ def send_dice( apihelper.send_dice( self.token, chat_id, emoji=emoji, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id)) @@ -2127,7 +2137,8 @@ def send_photo( message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2181,6 +2192,9 @@ def send_photo( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2212,7 +2226,8 @@ def send_photo( self.token, chat_id, photo, caption=caption, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) + message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id)) @@ -2232,7 +2247,8 @@ def send_audio( message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -2305,6 +2321,9 @@ def send_audio( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2339,7 +2358,8 @@ def send_audio( self.token, chat_id, audio, caption=caption, duration=duration, performer=performer, title=title, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id)) ) @@ -2356,7 +2376,8 @@ def send_voice( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -2410,6 +2431,9 @@ def send_voice( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -2439,7 +2463,8 @@ def send_voice( self.token, chat_id, voice, caption=caption, duration=duration, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id) ) @@ -2460,7 +2485,8 @@ def send_document( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send general files. @@ -2526,6 +2552,9 @@ def send_document( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2565,7 +2594,8 @@ def send_document( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption=caption, thumbnail=thumbnail, caption_entities=caption_entities, disable_content_type_detection=disable_content_type_detection, visible_file_name=visible_file_name, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, + business_connection_id=business_connection_id, message_effect_id=message_effect_id) ) @@ -2582,7 +2612,8 @@ def send_sticker( message_thread_id: Optional[int]=None, emoji: Optional[str]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -2631,6 +2662,9 @@ def send_sticker( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2664,7 +2698,8 @@ def send_sticker( self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, - reply_parameters=reply_parameters, business_connection_id=business_connection_id) + reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id) ) @@ -2689,7 +2724,8 @@ def send_video( has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2763,6 +2799,9 @@ def send_video( :param business_connection_id: Identifier of a business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Identifier of a message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2803,7 +2842,7 @@ def send_video( supports_streaming=supports_streaming, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, - reply_parameters=reply_parameters, business_connection_id=business_connection_id) + reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id) ) @@ -2826,7 +2865,8 @@ def send_animation( has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -2899,6 +2939,9 @@ def send_animation( :param business_connection_id: Identifier of a business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2934,7 +2977,7 @@ def send_animation( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - has_spoiler=has_spoiler, business_connection_id=business_connection_id) + has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id) ) @@ -2952,7 +2995,8 @@ def send_video_note( message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -3010,6 +3054,9 @@ def send_video_note( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3042,7 +3089,8 @@ def send_video_note( apihelper.send_video_note( self.token, chat_id, data, duration=duration, length=length, reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, + business_connection_id=business_connection_id, message_effect_id=message_effect_id) ) @@ -3058,7 +3106,8 @@ def send_media_group( allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> List[types.Message]: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -3095,6 +3144,9 @@ def send_media_group( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -3128,7 +3180,7 @@ def send_media_group( result = apihelper.send_media_group( self.token, chat_id, media, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id) + business_connection_id=business_connection_id, message_effect_id=message_effect_id) return [types.Message.de_json(msg) for msg in result] @@ -3147,7 +3199,8 @@ def send_location( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -3203,6 +3256,9 @@ def send_location( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :parameter message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3232,7 +3288,8 @@ def send_location( self.token, chat_id, latitude, longitude, live_period=live_period, reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, proximity_alert_radius=proximity_alert_radius, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id) ) @@ -3354,7 +3411,8 @@ def send_venue( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -3417,6 +3475,9 @@ def send_venue( :param business_connection_id: Identifier of a business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3446,7 +3507,8 @@ def send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id=foursquare_id, foursquare_type=foursquare_type, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, google_place_id=google_place_id, google_place_type=google_place_type, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id) ) @@ -3461,7 +3523,8 @@ def send_contact( allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -3511,6 +3574,9 @@ def send_contact( :param business_connection_id: Identifier of a business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3539,7 +3605,8 @@ def send_contact( apihelper.send_contact( self.token, chat_id, phone_number, first_name, last_name=last_name, vcard=vcard, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, - protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, + business_connection_id=business_connection_id, message_effect_id=message_effect_id) ) @@ -4707,7 +4774,8 @@ def send_game( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Used to send the game. @@ -4746,6 +4814,9 @@ def send_game( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -4777,7 +4848,8 @@ def send_game( apihelper.send_game( self.token, chat_id, game_short_name, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, + message_effect_id=message_effect_id) ) @@ -4881,7 +4953,8 @@ def send_invoice( suggested_tip_amounts: Optional[List[int]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Sends invoice. @@ -4986,6 +5059,9 @@ def send_invoice( :param reply_parameters: Required if the message is a reply. Additional interface options. :type reply_parameters: :obj:`types.ReplyParameters` + :param message_effect_id: The identifier of a message effect, which will be applied to the sent message + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5024,7 +5100,8 @@ def send_invoice( disable_notification=disable_notification, reply_markup=reply_markup, provider_data=provider_data, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts) + max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts, + message_effect_id=message_effect_id) ) def create_invoice_link(self, @@ -5155,7 +5232,7 @@ def send_poll( business_connection_id: Optional[str]=None, question_parse_mode: Optional[str] = None, question_entities: Optional[List[types.MessageEntity]] = None, - ) -> types.Message: + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -5234,6 +5311,9 @@ def send_poll( :param question_entities: A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question_parse_mode :type question_entities: :obj:`list` of :obj:`MessageEntity` + :param message_effect_id: Unique identifier of the message effect to apply to the sent message + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5288,7 +5368,8 @@ def send_poll( reply_markup=reply_markup, timeout=timeout, explanation_entities=explanation_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - question_parse_mode=question_parse_mode, question_entities=question_entities) + question_parse_mode=question_parse_mode, question_entities=question_entities, + message_effect_id=message_effect_id) ) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index f5eda28c0..ae080aea8 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3061,7 +3061,8 @@ async def send_message( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, link_preview_options: Optional[types.LinkPreviewOptions]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send text messages. @@ -3117,6 +3118,9 @@ async def send_message( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3171,7 +3175,8 @@ async def send_message( await asyncio_helper.send_message( self.token, chat_id, text, reply_markup, parse_mode, disable_notification, timeout, - entities, protect_content, message_thread_id, reply_parameters, link_preview_options, business_connection_id)) + entities, protect_content, message_thread_id, reply_parameters, link_preview_options, business_connection_id, + message_effect_id=message_effect_id)) async def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -3445,7 +3450,8 @@ async def send_dice( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -3487,6 +3493,9 @@ async def send_dice( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3517,7 +3526,7 @@ async def send_dice( return types.Message.de_json( await asyncio_helper.send_dice( self.token, chat_id, emoji, disable_notification, - reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id)) + reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_photo( @@ -3533,7 +3542,8 @@ async def send_photo( message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -3587,6 +3597,9 @@ async def send_photo( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3620,7 +3633,7 @@ async def send_photo( await asyncio_helper.send_photo( self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id)) + protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -3638,7 +3651,8 @@ async def send_audio( message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -3711,6 +3725,9 @@ async def send_audio( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3747,7 +3764,7 @@ async def send_audio( await asyncio_helper.send_audio( self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id)) + caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], @@ -3762,7 +3779,8 @@ async def send_voice( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -3816,6 +3834,9 @@ async def send_voice( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -3847,7 +3868,7 @@ async def send_voice( await asyncio_helper.send_voice( self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, reply_parameters, business_connection_id)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_document( self, chat_id: Union[int, str], document: Union[Any, str], @@ -3867,7 +3888,8 @@ async def send_document( message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send general files. @@ -3933,6 +3955,9 @@ async def send_document( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3977,7 +4002,7 @@ async def send_document( disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content, - message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) + message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id)) async def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], @@ -3991,7 +4016,8 @@ async def send_sticker( message_thread_id: Optional[int]=None, emoji: Optional[str]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -4040,6 +4066,9 @@ async def send_sticker( :param business_connection_id: Unique identifier for the target business connection :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier for the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4078,7 +4107,7 @@ async def send_sticker( reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id)) + message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id)) async def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -4101,7 +4130,8 @@ async def send_video( has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4175,6 +4205,9 @@ async def send_video( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4216,7 +4249,7 @@ async def send_video( await asyncio_helper.send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, - caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id)) + caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -4237,7 +4270,8 @@ async def send_animation( has_spoiler: Optional[bool]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -4310,6 +4344,9 @@ async def send_animation( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4346,7 +4383,8 @@ async def send_animation( await asyncio_helper.send_animation( self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id)) + caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, + message_effect_id=message_effect_id)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -4362,7 +4400,8 @@ async def send_video_note( message_thread_id: Optional[int]=None, thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -4420,6 +4459,9 @@ async def send_video_note( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4454,7 +4496,7 @@ async def send_video_note( return types.Message.de_json( await asyncio_helper.send_video_note( self.token, chat_id, data, duration, length, reply_markup, - disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id)) + disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_media_group( self, chat_id: Union[int, str], @@ -4468,7 +4510,8 @@ async def send_media_group( allow_sending_without_reply: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> List[types.Message]: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -4505,6 +4548,9 @@ async def send_media_group( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -4538,7 +4584,7 @@ async def send_media_group( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = await asyncio_helper.send_media_group( - self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id) + self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id) return [types.Message.de_json(msg) for msg in result] async def send_location( @@ -4556,7 +4602,8 @@ async def send_location( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -4612,6 +4659,9 @@ async def send_location( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4644,7 +4694,7 @@ async def send_location( self.token, chat_id, latitude, longitude, live_period, reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, - protect_content, message_thread_id, reply_parameters, business_connection_id)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def edit_message_live_location( self, latitude: float, longitude: float, @@ -4760,7 +4810,8 @@ async def send_venue( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -4824,6 +4875,9 @@ async def send_venue( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4855,7 +4909,7 @@ async def send_venue( await asyncio_helper.send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, disable_notification, reply_markup, timeout, - google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id)) + google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_contact( @@ -4870,7 +4924,8 @@ async def send_contact( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -4921,6 +4976,9 @@ async def send_contact( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param message_effect_id: Unique identifier of the message effect + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4952,7 +5010,7 @@ async def send_contact( await asyncio_helper.send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters, business_connection_id)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) async def send_chat_action( @@ -6063,7 +6121,8 @@ async def send_game( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - business_connection_id: Optional[str]=None) -> types.Message: + business_connection_id: Optional[str]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Used to send the game. @@ -6102,6 +6161,9 @@ async def send_game( :param business_connection_id: Identifier of the business connection. :type business_connection_id: :obj:`str` + :param message_effect_id: Identifier of the message effect. + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6132,7 +6194,7 @@ async def send_game( result = await asyncio_helper.send_game( self.token, chat_id, game_short_name, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters, business_connection_id) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id) return types.Message.de_json(result) async def set_game_score( @@ -6230,7 +6292,8 @@ async def send_invoice( suggested_tip_amounts: Optional[List[int]]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.Message: + reply_parameters: Optional[types.ReplyParameters]=None, + message_effect_id: Optional[str]=None) -> types.Message: """ Sends invoice. @@ -6335,6 +6398,9 @@ async def send_invoice( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + :param message_effect_id: The identifier of a message effect to be applied to the message + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6368,7 +6434,8 @@ async def send_invoice( photo_height, need_name, need_phone_number, need_email, need_shipping_address, send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification, reply_markup, provider_data, timeout, - max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters) + max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters, + message_effect_id=message_effect_id) return types.Message.de_json(result) @@ -6498,7 +6565,7 @@ async def send_poll( business_connection_id: Optional[str]=None, question_parse_mode: Optional[str] = None, question_entities: Optional[List[types.MessageEntity]] = None, - ) -> types.Message: + message_effect_id: Optional[str]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -6581,6 +6648,9 @@ async def send_poll( :param question_entities: A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question_parse_mode :type question_entities: :obj:`list` of :obj:`MessageEntity` + :param message_effect_id: Identifier of the message effect to apply to the sent message + :type message_effect_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6632,7 +6702,8 @@ async def send_poll( explanation, explanation_parse_mode, open_period, close_date, is_closed, disable_notification, reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters, - business_connection_id, question_parse_mode=question_parse_mode, question_entities=question_entities)) + business_connection_id, question_parse_mode=question_parse_mode, question_entities=question_entities, + message_effect_id=message_effect_id)) async def stop_poll( self, chat_id: Union[int, str], message_id: int, From 236518ee535240b3475d8d7bf05b0ed4836f9341 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 17:29:42 +0400 Subject: [PATCH 248/480] Update __init__.py --- telebot/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index ffc3b485b..56a24e0c7 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2360,7 +2360,6 @@ def send_audio( timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id)) - ) def send_voice( From a5090263dd8303ce20114b59b68be12bbba0c6b2 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 17:49:48 +0400 Subject: [PATCH 249/480] Added the field show_caption_above_media to the classes Message, InputMediaAnimation, InputMediaPhoto, InputMediaVideo, InlineQueryResultGif, InlineQueryResultMpeg4Gif, InlineQueryResultPhoto, InlineQueryResultVideo, InlineQueryResultCachedGif, InlineQueryResultCachedMpeg4Gif, InlineQueryResultCachedPhoto, and InlineQueryResultCachedVideo. --- telebot/types.py | 91 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index f5380e084..23146cffe 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -989,6 +989,9 @@ class Message(JsonDeserializable): commands, etc. that appear in the caption :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + :param show_caption_above_media: Optional. True, if the caption must be shown above the message media + :type show_caption_above_media: :obj:`bool` + :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation :type has_media_spoiler: :obj:`bool` @@ -1375,6 +1378,8 @@ def de_json(cls, json_string): opts['is_from_offline'] = obj['is_from_offline'] if 'effect_id' in obj: opts['effect_id'] = obj['effect_id'] + if 'show_caption_above_media' in obj: + opts['show_caption_above_media'] = obj['show_caption_above_media'] @@ -1485,6 +1490,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.business_connection_id: Optional[str] = None self.is_from_offline: Optional[bool] = None self.effect_id: Optional[str] = None + self.show_caption_above_media: Optional[bool] = None for key in options: setattr(self, key, options[key]) @@ -4454,11 +4460,15 @@ class InlineQueryResultPhoto(InlineQueryResultBase): :param input_message_content: Optional. Content of the message to be sent instead of the photo :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. If true, a caption is shown over the photo or video + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultPhoto` """ def __init__(self, id, photo_url, thumbnail_url, photo_width=None, photo_height=None, title=None, - description=None, caption=None, caption_entities=None, parse_mode=None, reply_markup=None, input_message_content=None): + description=None, caption=None, caption_entities=None, parse_mode=None, reply_markup=None, input_message_content=None, + show_caption_above_media=None): super().__init__('photo', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4467,6 +4477,7 @@ def __init__(self, id, photo_url, thumbnail_url, photo_width=None, photo_height= self.photo_width = photo_width self.photo_height = photo_height self.description = description + self.show_caption_above_media: Optional[bool] = show_caption_above_media @property def thumb_url(self): @@ -4483,6 +4494,8 @@ def to_dict(self): json_dict['photo_height'] = self.photo_height if self.description: json_dict['description'] = self.description + if self.show_caption_above_media: + json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -4537,13 +4550,16 @@ class InlineQueryResultGif(InlineQueryResultBase): :param input_message_content: Optional. Content of the message to be sent instead of the GIF animation :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. If true, a caption is shown over the photo or video + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultGif` """ def __init__(self, id, gif_url, thumbnail_url, gif_width=None, gif_height=None, title=None, caption=None, caption_entities=None, reply_markup=None, input_message_content=None, gif_duration=None, parse_mode=None, - thumbnail_mime_type=None): + thumbnail_mime_type=None, show_caption_above_media=None): super().__init__('gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4553,6 +4569,7 @@ def __init__(self, id, gif_url, thumbnail_url, gif_width=None, gif_height=None, self.thumbnail_url = thumbnail_url self.gif_duration = gif_duration self.thumbnail_mime_type = thumbnail_mime_type + self.show_caption_above_media: Optional[bool] = show_caption_above_media @property def thumb_url(self): @@ -4576,6 +4593,8 @@ def to_dict(self): json_dict['gif_duration'] = self.gif_duration if self.thumbnail_mime_type: json_dict['thumbnail_mime_type'] = self.thumbnail_mime_type + if self.show_caption_above_media: + json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -4630,13 +4649,16 @@ class InlineQueryResultMpeg4Gif(InlineQueryResultBase): :param input_message_content: Optional. Content of the message to be sent instead of the video animation :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. If true, a caption is shown over the photo or video + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultMpeg4Gif` """ def __init__(self, id, mpeg4_url, thumbnail_url, mpeg4_width=None, mpeg4_height=None, title=None, caption=None, caption_entities=None, parse_mode=None, reply_markup=None, input_message_content=None, mpeg4_duration=None, - thumbnail_mime_type=None): + thumbnail_mime_type=None, show_caption_above_media=None): super().__init__('mpeg4_gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4646,6 +4668,7 @@ def __init__(self, id, mpeg4_url, thumbnail_url, mpeg4_width=None, mpeg4_height= self.thumbnail_url = thumbnail_url self.mpeg4_duration = mpeg4_duration self.thumbnail_mime_type = thumbnail_mime_type + self.show_caption_above_media: Optional[bool] = show_caption_above_media @property def thumb_url(self): @@ -4669,6 +4692,8 @@ def to_dict(self): json_dict['mpeg4_duration '] = self.mpeg4_duration if self.thumbnail_mime_type: json_dict['thumbnail_mime_type'] = self.thumbnail_mime_type + if self.show_caption_above_media: + json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -4727,13 +4752,16 @@ class InlineQueryResultVideo(InlineQueryResultBase): required if InlineQueryResultVideo is used to send an HTML-page as a result (e.g., a YouTube video). :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. If true, a caption is shown over the video + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultVideo` """ def __init__(self, id, video_url, mime_type, thumbnail_url, title, caption=None, caption_entities=None, parse_mode=None, video_width=None, video_height=None, video_duration=None, - description=None, reply_markup=None, input_message_content=None): + description=None, reply_markup=None, input_message_content=None, show_caption_above_media=None): super().__init__('video', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4744,6 +4772,7 @@ def __init__(self, id, video_url, mime_type, thumbnail_url, self.video_height = video_height self.video_duration = video_duration self.description = description + self.show_caption_above_media: Optional[bool] = show_caption_above_media @property def thumb_url(self): @@ -4761,6 +4790,8 @@ def to_dict(self): json_dict['video_duration'] = self.video_duration if self.description: json_dict['description'] = self.description + if self.show_caption_above_media: + json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -5330,6 +5361,7 @@ def __init__(self): self.parse_mode = None self.caption_entities = None self.payload_dic = {} + self.show_caption_above_media = None def to_json(self): json_dict = self.payload_dic @@ -5349,6 +5381,8 @@ def to_json(self): json_dict['parse_mode'] = self.parse_mode if self.caption_entities: json_dict['caption_entities'] = MessageEntity.to_list_of_dicts(self.caption_entities) + if self.show_caption_above_media: + json_dict['show_caption_above_media'] = self.show_caption_above_media return json.dumps(json_dict) @@ -5391,12 +5425,15 @@ class InlineQueryResultCachedPhoto(InlineQueryResultCachedBase): :param input_message_content: Optional. Content of the message to be sent instead of the photo :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. Pass True, if a caption is not required for the media + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedPhoto` """ def __init__(self, id, photo_file_id, title=None, description=None, caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None): + reply_markup=None, input_message_content=None, show_caption_above_media=None): InlineQueryResultCachedBase.__init__(self) self.type = 'photo' self.id = id @@ -5409,6 +5446,7 @@ def __init__(self, id, photo_file_id, title=None, description=None, self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['photo_file_id'] = photo_file_id + self.show_caption_above_media: Optional[bool] = show_caption_above_media # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -5446,12 +5484,15 @@ class InlineQueryResultCachedGif(InlineQueryResultCachedBase): :param input_message_content: Optional. Content of the message to be sent instead of the GIF animation :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. Pass True, if a caption is not required for the media + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedGif` """ def __init__(self, id, gif_file_id, title=None, description=None, caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None): + reply_markup=None, input_message_content=None, show_caption_above_media=None): InlineQueryResultCachedBase.__init__(self) self.type = 'gif' self.id = id @@ -5464,6 +5505,7 @@ def __init__(self, id, gif_file_id, title=None, description=None, self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['gif_file_id'] = gif_file_id + self.show_caption_above_media: Optional[bool] = show_caption_above_media # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -5501,12 +5543,15 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResultCachedBase): :param input_message_content: Optional. Content of the message to be sent instead of the video animation :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. Pass True, if caption should be shown above the media + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedMpeg4Gif` """ def __init__(self, id, mpeg4_file_id, title=None, description=None, caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None): + reply_markup=None, input_message_content=None, show_caption_above_media=None): InlineQueryResultCachedBase.__init__(self) self.type = 'mpeg4_gif' self.id = id @@ -5519,7 +5564,7 @@ def __init__(self, id, mpeg4_file_id, title=None, description=None, self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['mpeg4_file_id'] = mpeg4_file_id - + self.show_caption_above_media: Optional[bool] = show_caption_above_media # noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedSticker(InlineQueryResultCachedBase): @@ -5654,13 +5699,16 @@ class InlineQueryResultCachedVideo(InlineQueryResultCachedBase): :param input_message_content: Optional. Content of the message to be sent instead of the video :type input_message_content: :class:`telebot.types.InputMessageContent` + :param show_caption_above_media: Optional. Pass True, if a caption is not required for the media + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedVideo` """ def __init__(self, id, video_file_id, title, description=None, caption=None, caption_entities = None, parse_mode=None, reply_markup=None, - input_message_content=None): + input_message_content=None, show_caption_above_media=None): InlineQueryResultCachedBase.__init__(self) self.type = 'video' self.id = id @@ -5673,6 +5721,7 @@ def __init__(self, id, video_file_id, title, description=None, self.input_message_content = input_message_content self.parse_mode = parse_mode self.payload_dic['video_file_id'] = video_file_id + self.show_caption_above_media: Optional[bool] = show_caption_above_media # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -6575,10 +6624,13 @@ class InputMediaPhoto(InputMedia): :param has_spoiler: Optional. True, if the uploaded photo is a spoiler :type has_spoiler: :obj:`bool` + :param show_caption_above_media: Optional. True, if the caption should be shown above the photo + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InputMediaPhoto` """ - def __init__(self, media, caption=None, parse_mode=None, caption_entities=None, has_spoiler=None): + def __init__(self, media, caption=None, parse_mode=None, caption_entities=None, has_spoiler=None, show_caption_above_media=None): if service_utils.is_pil_image(media): media = service_utils.pil_image_to_file(media) @@ -6586,11 +6638,14 @@ def __init__(self, media, caption=None, parse_mode=None, caption_entities=None, type="photo", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) self.has_spoiler: Optional[bool] = has_spoiler + self.show_caption_above_media: Optional[bool] = show_caption_above_media def to_dict(self): ret = super(InputMediaPhoto, self).to_dict() if self.has_spoiler is not None: ret['has_spoiler'] = self.has_spoiler + if self.show_caption_above_media is not None: + ret['show_caption_above_media'] = self.show_caption_above_media return ret @@ -6638,11 +6693,14 @@ class InputMediaVideo(InputMedia): :param has_spoiler: Optional. True, if the uploaded video is a spoiler :type has_spoiler: :obj:`bool` + :param show_caption_above_media: Optional. True, if the caption should be shown above the video + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InputMediaVideo` """ def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption_entities=None, - width=None, height=None, duration=None, supports_streaming=None, has_spoiler=None): + width=None, height=None, duration=None, supports_streaming=None, has_spoiler=None, show_caption_above_media=None): super(InputMediaVideo, self).__init__( type="video", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) self.thumbnail = thumbnail @@ -6651,6 +6709,7 @@ def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption self.duration = duration self.supports_streaming = supports_streaming self.has_spoiler: Optional[bool] = has_spoiler + self.show_caption_above_media: Optional[bool] = show_caption_above_media @property def thumb(self): @@ -6671,6 +6730,8 @@ def to_dict(self): ret['supports_streaming'] = self.supports_streaming if self.has_spoiler is not None: ret['has_spoiler'] = self.has_spoiler + if self.show_caption_above_media is not None: + ret['show_caption_above_media'] = self.show_caption_above_media return ret @@ -6715,11 +6776,14 @@ class InputMediaAnimation(InputMedia): :param has_spoiler: Optional. True, if the uploaded animation is a spoiler :type has_spoiler: :obj:`bool` + :param show_caption_above_media: Optional. True, if the caption should be shown above the animation + :type show_caption_above_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.InputMediaAnimation` """ def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption_entities=None, - width=None, height=None, duration=None, has_spoiler=None): + width=None, height=None, duration=None, has_spoiler=None, show_caption_above_media=None): super(InputMediaAnimation, self).__init__( type="animation", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) self.thumbnail = thumbnail @@ -6727,6 +6791,7 @@ def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption self.height = height self.duration = duration self.has_spoiler: Optional[bool] = has_spoiler + self.show_caption_above_media: Optional[bool] = show_caption_above_media @property def thumb(self): @@ -6745,6 +6810,8 @@ def to_dict(self): ret['duration'] = self.duration if self.has_spoiler is not None: ret['has_spoiler'] = self.has_spoiler + if self.show_caption_above_media is not None: + ret['show_caption_above_media'] = self.show_caption_above_media return ret From d66028285be722d5d21d63b6b57ffc10ef892efa Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 18:03:23 +0400 Subject: [PATCH 250/480] attempt 2: Added the parameter message_effect_id to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendPoll, sendDice, sendInvoice, sendGame, and sendMediaGroup. --- telebot/apihelper.py | 71 ++++++++++++++++++++++++++++++--------- telebot/asyncio_helper.py | 68 ++++++++++++++++++++++++++++--------- 2 files changed, 107 insertions(+), 32 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 0ef0d2211..d230639c7 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -245,7 +245,7 @@ def send_message( parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, link_preview_options=None, - business_connection_id=None): + business_connection_id=None, message_effect_id=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -268,6 +268,8 @@ def send_message( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, method='post') @@ -454,7 +456,7 @@ def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, - business_connection_id=None): + business_connection_id=None, message_effect_id=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -473,6 +475,8 @@ def send_dice( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) @@ -481,7 +485,7 @@ def send_photo( caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -513,13 +517,16 @@ def send_photo( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_media_group( token, chat_id, media, disable_notification=None, - timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): + timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendMediaGroup' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -535,6 +542,8 @@ def send_media_group( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request( token, method_url, params=payload, method='post' if files else 'get', @@ -547,7 +556,8 @@ def send_location( reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, - message_thread_id=None, reply_parameters=None, business_connection_id=None): + message_thread_id=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -572,6 +582,8 @@ def send_location( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) @@ -623,7 +635,8 @@ def send_venue( token, chat_id, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, - google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): + google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -648,13 +661,16 @@ def send_venue( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -675,6 +691,8 @@ def send_contact( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) @@ -694,7 +712,7 @@ def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=Non def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -740,6 +758,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') @@ -748,7 +768,7 @@ def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, - has_spoiler=None, business_connection_id=None): + has_spoiler=None, business_connection_id=None, message_effect_id=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -792,12 +812,15 @@ def send_animation( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -827,12 +850,14 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None, reply_parameters=None,business_connection_id=None): + message_thread_id=None, reply_parameters=None,business_connection_id=None, message_effect_id=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -868,12 +893,15 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, - caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): + caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -915,13 +943,16 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, - protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None, business_connection_id=None): + protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -964,6 +995,8 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1417,7 +1450,7 @@ def delete_message(token, chat_id, message_id, timeout=None): def send_game( token, chat_id, game_short_name, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: @@ -1434,6 +1467,8 @@ def send_game( payload['reply_parameters'] = reply_parameters.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) @@ -1499,7 +1534,7 @@ def send_invoice( send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None, reply_parameters=None): + protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1579,6 +1614,8 @@ def send_invoice( payload['message_thread_id'] = message_thread_id if reply_parameters is not None: payload['reply_parameters'] = reply_parameters.to_json() + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) @@ -1827,7 +1864,7 @@ def send_poll( is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, - reply_parameters=None, business_connection_id=None, question_parse_mode=None, question_entities=None): + reply_parameters=None, business_connection_id=None, question_parse_mode=None, question_entities=None, message_effect_id=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1876,6 +1913,8 @@ def send_poll( payload['question_parse_mode'] = question_parse_mode if question_entities: payload['question_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(question_entities)) + if message_effect_id: + payload['message_effect_id'] = message_effect_id return _make_request(token, method_url, params=payload) def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None): diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index d63ec5773..aa6a5cd68 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -281,7 +281,7 @@ async def send_message( reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, - message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None): + message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None, message_effect_id=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -304,6 +304,8 @@ async def send_message( params['message_thread_id'] = message_thread_id if business_connection_id: params['business_connection_id'] = business_connection_id + if message_effect_id: + params['message_effect_id'] = message_effect_id return await _process_request(token, method_name, params=params) @@ -442,7 +444,7 @@ async def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, - message_thread_id=None,reply_parameters=None, business_connection_id=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -461,6 +463,8 @@ async def send_dice( payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) @@ -470,7 +474,7 @@ async def send_photo( parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, - business_connection_id=None): + business_connection_id=None, message_effect_id=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -502,13 +506,15 @@ async def send_photo( payload['has_spoiler'] = has_spoiler if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_media_group( token, chat_id, media, disable_notification=None, - timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): + timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendMediaGroup' media_json, files = await convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -524,6 +530,8 @@ async def send_media_group( payload['reply_parameters'] = json.dumps(reply_parameters.to_dict()) if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request( token, method_url, params=payload, method='post' if files else 'get', @@ -535,7 +543,8 @@ async def send_location( live_period=None, reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, - proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): + proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -560,6 +569,8 @@ async def send_location( payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) @@ -612,7 +623,8 @@ async def send_venue( foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, - google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): + google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -637,13 +649,15 @@ async def send_venue( payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) async def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -664,6 +678,8 @@ async def send_contact( payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) @@ -682,7 +698,8 @@ async def send_chat_action(token, chat_id, action, timeout=None, message_thread_ async def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, - protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None): + protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -728,6 +745,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['has_spoiler'] = has_spoiler if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -735,7 +754,7 @@ async def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, width=None, height=None, protect_content=None, message_thread_id=None, - has_spoiler=None,reply_parameters=None, business_connection_id=None): + has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -779,12 +798,14 @@ async def send_animation( payload['has_spoiler'] = has_spoiler if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None, message_effect_id=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -814,12 +835,14 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_ payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None,reply_parameters=None, business_connection_id=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -855,12 +878,15 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, rep payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, - caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): + caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, + message_effect_id=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -902,13 +928,15 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None, - message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None): + message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -951,6 +979,8 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m payload['emoji'] = emoji if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1400,7 +1430,7 @@ async def delete_message(token, chat_id, message_id, timeout=None): async def send_game( token, chat_id, game_short_name, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: @@ -1417,6 +1447,8 @@ async def send_game( payload['message_thread_id'] = message_thread_id if business_connection_id: payload['business_connection_id'] = business_connection_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) @@ -1482,7 +1514,7 @@ async def send_invoice( send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None, reply_parameters=None): + protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1563,6 +1595,8 @@ async def send_invoice( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) @@ -1809,7 +1843,7 @@ async def send_poll( explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, - reply_parameters=None,business_connection_id=None, question_parse_mode=None, question_entities=None): + reply_parameters=None,business_connection_id=None, question_parse_mode=None, question_entities=None, message_effect_id=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -1859,6 +1893,8 @@ async def send_poll( payload['question_parse_mode'] = question_parse_mode if question_entities: payload['question_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(question_entities)) + if message_effect_id: + payload['message_effect_id'] = message_effect_id return await _process_request(token, method_url, params=payload) From 4830720ce8c28d8f5ff52ce736b60a37f91d15c5 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 18:15:32 +0400 Subject: [PATCH 251/480] Added the parameter show_caption_above_media to the methods sendAnimation, sendPhoto, sendVideo, copyMessage, and editMessageCaption. --- telebot/__init__.py | 41 ++++++++++++++++++++++++++++---------- telebot/apihelper.py | 22 +++++++++++++++----- telebot/async_telebot.py | 42 +++++++++++++++++++++++++++++---------- telebot/asyncio_helper.py | 20 ++++++++++++++----- 4 files changed, 95 insertions(+), 30 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 56a24e0c7..9c23526eb 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1818,7 +1818,7 @@ def copy_message( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID: + reply_parameters: Optional[types.ReplyParameters]=None, """ Use this method to copy messages of any kind. @@ -1866,6 +1866,9 @@ def copy_message( :param reply_parameters: Additional parameters for replies to messages :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -1896,7 +1899,7 @@ def copy_message( apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters)) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, show_caption_above_media=show_caption_above_media)) def delete_message(self, chat_id: Union[int, str], message_id: int, @@ -2138,7 +2141,8 @@ def send_photo( has_spoiler: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + show_caption_above_media: Optional[bool]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2195,6 +2199,9 @@ def send_photo( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2227,7 +2234,7 @@ def send_photo( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media)) @@ -2724,7 +2731,8 @@ def send_video( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + show_caption_above_media: Optional[bool]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2801,6 +2809,9 @@ def send_video( :param message_effect_id: Identifier of a message effect :type message_effect_id: :obj:`str` + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2841,7 +2852,8 @@ def send_video( supports_streaming=supports_streaming, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, - reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id) + reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + show_caption_above_media=show_caption_above_media) ) @@ -2865,7 +2877,8 @@ def send_animation( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + show_caption_above_media: Optional[bool]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -2941,6 +2954,9 @@ def send_animation( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2976,7 +2992,8 @@ def send_animation( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id) + has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, + show_caption_above_media=show_caption_above_media) ) @@ -5479,7 +5496,8 @@ def edit_message_caption( inline_message_id: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + show_caption_above_media: Optional[bool]=None) -> Union[types.Message, bool]: """ Use this method to edit captions of messages. @@ -5506,6 +5524,9 @@ def edit_message_caption( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`InlineKeyboardMarkup` + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` | :obj:`bool` """ @@ -5513,7 +5534,7 @@ def edit_message_caption( result = apihelper.edit_message_caption( self.token, caption, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup) + parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup, show_caption_above_media=show_caption_above_media) if type(result) == bool: return result diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d230639c7..78dee41a8 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -485,7 +485,8 @@ def send_photo( caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, + show_caption_above_media=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -519,6 +520,8 @@ def send_photo( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload, files=files, method='post') @@ -712,7 +715,8 @@ def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=Non def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, + show_caption_above_media=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -760,6 +764,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload, files=files, method='post') @@ -768,7 +774,7 @@ def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, - has_spoiler=None, business_connection_id=None, message_effect_id=None): + has_spoiler=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -814,6 +820,8 @@ def send_animation( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1390,7 +1398,7 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None, - parse_mode=None, caption_entities=None,reply_markup=None): + parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None): method_url = r'editMessageCaption' payload = {'caption': caption} if chat_id: @@ -1405,6 +1413,8 @@ def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_m payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload, method='post') @@ -2016,7 +2026,7 @@ def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notifica return _make_request(token, method_url, params=payload) def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, - message_thread_id=None, protect_content=None, remove_caption=None): + message_thread_id=None, protect_content=None, remove_caption=None, show_caption_above_media=None): method_url = 'copyMessages' payload = { 'chat_id': chat_id, @@ -2031,6 +2041,8 @@ def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notificatio payload['protect_content'] = protect_content if remove_caption is not None: payload['remove_caption'] = remove_caption + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ae080aea8..abd45a3c1 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3234,7 +3234,8 @@ async def copy_message( reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - reply_parameters: Optional[types.ReplyParameters]=None) -> types.MessageID: + reply_parameters: Optional[types.ReplyParameters]=None, + show_caption_above_media: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. @@ -3282,6 +3283,9 @@ async def copy_message( :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -3313,7 +3317,7 @@ async def copy_message( return types.MessageID.de_json( await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, disable_notification, reply_markup, - timeout, protect_content, message_thread_id, reply_parameters)) + timeout, protect_content, message_thread_id, reply_parameters, show_caption_above_media=show_caption_above_media)) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -3543,7 +3547,8 @@ async def send_photo( has_spoiler: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + show_caption_above_media: Optional[bool]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -3600,6 +3605,9 @@ async def send_photo( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3633,7 +3641,8 @@ async def send_photo( await asyncio_helper.send_photo( self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + show_caption_above_media=show_caption_above_media)) async def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -4131,7 +4140,8 @@ async def send_video( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + show_caption_above_media: Optional[bool]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4208,6 +4218,9 @@ async def send_video( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4249,7 +4262,8 @@ async def send_video( await asyncio_helper.send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, - caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + show_caption_above_media=show_caption_above_media)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -4271,7 +4285,8 @@ async def send_animation( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + show_caption_above_media: Optional[bool]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -4347,6 +4362,9 @@ async def send_animation( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4384,7 +4402,7 @@ async def send_animation( self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -6806,7 +6824,8 @@ async def edit_message_caption( inline_message_id: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + show_caption_above_media: Optional[bool]=None) -> Union[types.Message, bool]: """ Use this method to edit captions of messages. @@ -6833,13 +6852,16 @@ async def edit_message_caption( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`InlineKeyboardMarkup` + :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. + :type show_caption_above_media: :obj:`bool` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` | :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode result = await asyncio_helper.edit_message_caption(self.token, caption, chat_id, message_id, inline_message_id, - parse_mode, caption_entities, reply_markup) + parse_mode, caption_entities, reply_markup, show_caption_above_media=show_caption_above_media) if type(result) == bool: return result return types.Message.de_json(result) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index aa6a5cd68..630a351a9 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -416,7 +416,7 @@ async def forward_message( async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, - reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None): + reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -437,6 +437,8 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return await _process_request(token, method_url, params=payload) @@ -474,7 +476,7 @@ async def send_photo( parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, - business_connection_id=None, message_effect_id=None): + business_connection_id=None, message_effect_id=None, show_caption_above_media=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -508,6 +510,8 @@ async def send_photo( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -699,7 +703,7 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, show_caption_above_media=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -747,6 +751,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -754,7 +760,7 @@ async def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, width=None, height=None, protect_content=None, message_thread_id=None, - has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -800,6 +806,8 @@ async def send_animation( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1370,7 +1378,7 @@ async def edit_message_text(token, text, chat_id=None, message_id=None, inline_m async def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None, - parse_mode=None, caption_entities=None,reply_markup=None): + parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None): method_url = r'editMessageCaption' payload = {'caption': caption} if chat_id: @@ -1385,6 +1393,8 @@ async def edit_message_caption(token, caption, chat_id=None, message_id=None, in payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return await _process_request(token, method_url, params=payload, method='post') From a95d100b23d1213d63b2954a3615fd11ed64d58f Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 28 May 2024 18:24:17 +0400 Subject: [PATCH 252/480] entity fixes --- telebot/__init__.py | 4 ++++ telebot/formatting.py | 2 ++ telebot/types.py | 12 ++++++------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 9c23526eb..263802de0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1819,6 +1819,7 @@ def copy_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, + show_caption_above_media: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. @@ -1829,6 +1830,7 @@ def copy_message( :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) :type from_chat_id: :obj:`int` or :obj:`str` + :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` @@ -1872,7 +1874,9 @@ def copy_message( :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` + """ + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification parse_mode = self.parse_mode if (parse_mode is None) else parse_mode protect_content = self.protect_content if (protect_content is None) else protect_content diff --git a/telebot/formatting.py b/telebot/formatting.py index dd7309416..09687ec9f 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -397,6 +397,8 @@ def apply_html_entities(text: str, entities: Optional[List], custom_subs: Option "spoiler": "{text}", "custom_emoji": "{text}", "blockquote": "
{text}
", + "expandable_blockquote": "
{text}
", + } if custom_subs: diff --git a/telebot/types.py b/telebot/types.py index 23146cffe..6479f3468 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1598,12 +1598,12 @@ class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#messageentity - :param type: Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag), “cashtag” - ($USD), “bot_command” (/start@jobs_bot), “url” (https://telegram.org), “email” - (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), “bold” (bold text), “italic” (italic text), - “underline” (underlined text), “strikethrough” (strikethrough text), “spoiler” (spoiler message), “code” - (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), “text_mention” (for users - without usernames), “custom_emoji” (for inline custom emoji stickers) + :param type: Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag), “cashtag” ($USD), + “bot_command” (/start@jobs_bot),“url” (https://telegram.org), “email” (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), + “bold” (bold text), “italic” (italic text), “underline” (underlined text), “strikethrough” (strikethrough text), + “spoiler” (spoiler message), “blockquote” (block quotation), “expandable_blockquote” (collapsed-by-default block quotation), + “code” (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), + “text_mention” (for users without usernames), “custom_emoji” (for inline custom emoji stickers) :type type: :obj:`str` :param offset: Offset in UTF-16 code units to the start of the entity From 90714218761d87194121c82774197a745f3c84d8 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 31 May 2024 14:54:47 +0400 Subject: [PATCH 253/480] Fix #2287 Fix #2287 --- telebot/types.py | 1 - 1 file changed, 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index cfbe447fd..1438cf762 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9899,7 +9899,6 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['document'] = Document.de_json(obj['document']) - obj['fill'] = BackgroundFill.de_json(obj['fill']) return cls(**obj) def __init__(self, type, document, dark_theme_dimming, is_blurred=None, is_moving=None, **kwargs): From 2e4f92d96982021dce8dbea77562130388c8c264 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 31 May 2024 19:24:09 +0400 Subject: [PATCH 254/480] Fixes to bot API 7.4 --- telebot/__init__.py | 10 ++++++---- telebot/apihelper.py | 12 ++++++++---- telebot/async_telebot.py | 10 ++++++---- telebot/asyncio_helper.py | 14 +++++++++----- telebot/types.py | 10 +++++----- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 263802de0..99c492954 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4954,7 +4954,7 @@ def get_game_high_scores( def send_invoice( self, chat_id: Union[int, str], title: str, description: str, - invoice_payload: str, provider_token: str, currency: str, + invoice_payload: str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, photo_url: Optional[str]=None, photo_size: Optional[int]=None, photo_width: Optional[int]=None, photo_height: Optional[int]=None, @@ -4993,7 +4993,8 @@ def send_invoice( use for your internal processes. :type invoice_payload: :obj:`str` - :param provider_token: Payments provider token, obtained via @Botfather + :param provider_token: Payments provider token, obtained via @Botfather; Pass None to omit the parameter + to use "XTR" currency :type provider_token: :obj:`str` :param currency: Three-letter ISO 4217 currency code, @@ -5125,7 +5126,7 @@ def send_invoice( ) def create_invoice_link(self, - title: str, description: str, payload:str, provider_token: str, + title: str, description: str, payload:str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, @@ -5159,7 +5160,8 @@ def create_invoice_link(self, use for your internal processes. :type payload: :obj:`str` - :param provider_token: Payments provider token, obtained via @Botfather + :param provider_token: Payments provider token, obtained via @Botfather; Pass None to omit the parameter + to use "XTR" currency :type provider_token: :obj:`str` :param currency: Three-letter ISO 4217 currency code, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 78dee41a8..4d984dcf1 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1580,7 +1580,7 @@ def send_invoice( """ method_url = r'sendInvoice' payload = {'chat_id': chat_id, 'title': title, 'description': description, 'payload': invoice_payload, - 'provider_token': provider_token, 'currency': currency, + 'currency': currency, 'prices': _convert_list_json_serializable(prices)} if start_parameter: payload['start_parameter'] = start_parameter @@ -1626,6 +1626,8 @@ def send_invoice( payload['reply_parameters'] = reply_parameters.to_json() if message_effect_id: payload['message_effect_id'] = message_effect_id + if provider_token is not None: + payload['provider_token'] = provider_token return _make_request(token, method_url, params=payload) @@ -1666,13 +1668,13 @@ def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_message=No def refund_star_payment(token, user_id, telegram_payment_charge_id): method_url = 'refundStarPayment' payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id} - return _make_request(token, method_url, params=payload, method='post') + return _make_request(token, method_url, params=payload) def unpin_all_general_forum_topic_messages(token, chat_id): method_url = 'unpinAllGeneralForumTopicMessages' payload = {'chat_id': chat_id} - return _make_request(token, method_url, params=payload, method='post') + return _make_request(token, method_url, params=payload) # InlineQuery @@ -1835,7 +1837,7 @@ def create_invoice_link(token, title, description, payload, provider_token, need_email=None, need_shipping_address=None, send_phone_number_to_provider=None, send_email_to_provider=None, is_flexible=None): method_url = r'createInvoiceLink' - payload = {'title': title, 'description': description, 'payload': payload, 'provider_token': provider_token, + payload = {'title': title, 'description': description, 'payload': payload, 'currency': currency, 'prices': _convert_list_json_serializable(prices)} if max_tip_amount: payload['max_tip_amount'] = max_tip_amount @@ -1865,6 +1867,8 @@ def create_invoice_link(token, title, description, payload, provider_token, payload['send_email_to_provider'] = send_email_to_provider if is_flexible is not None: payload['is_flexible'] = is_flexible + if provider_token is not None: + payload['provider_token'] = provider_token return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index abd45a3c1..be3135739 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6291,7 +6291,7 @@ async def get_game_high_scores( async def send_invoice( self, chat_id: Union[int, str], title: str, description: str, - invoice_payload: str, provider_token: str, currency: str, + invoice_payload: str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, photo_url: Optional[str]=None, photo_size: Optional[int]=None, photo_width: Optional[int]=None, photo_height: Optional[int]=None, @@ -6330,7 +6330,8 @@ async def send_invoice( use for your internal processes. :type invoice_payload: :obj:`str` - :param provider_token: Payments provider token, obtained via @Botfather + :param provider_token: Payments provider token, obtained via @Botfather; Pass None to omit the parameter + to use "XTR" currency :type provider_token: :obj:`str` :param currency: Three-letter ISO 4217 currency code, @@ -6458,7 +6459,7 @@ async def send_invoice( async def create_invoice_link(self, - title: str, description: str, payload:str, provider_token: str, + title: str, description: str, payload:str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, @@ -6492,7 +6493,8 @@ async def create_invoice_link(self, use for your internal processes. :type payload: :obj:`str` - :param provider_token: Payments provider token, obtained via @Botfather + :param provider_token: Payments provider token, obtained via @Botfather; Pass None to omit the parameter + to use "XTR" currency :type provider_token: :obj:`str` :param currency: Three-letter ISO 4217 currency code, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 630a351a9..e7838fbb4 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1561,8 +1561,8 @@ async def send_invoice( """ method_url = r'sendInvoice' payload = {'chat_id': chat_id, 'title': title, 'description': description, 'payload': invoice_payload, - 'provider_token': provider_token, 'currency': currency, - 'prices': await _convert_list_json_serializable(prices)} + 'currency': currency, + 'prices': await _convert_list_json_serializable(prices)} if start_parameter: payload['start_parameter'] = start_parameter if photo_url: @@ -1607,6 +1607,8 @@ async def send_invoice( payload['message_thread_id'] = message_thread_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if provider_token is not None: + payload['provider_token'] = provider_token return await _process_request(token, method_url, params=payload) @@ -1648,13 +1650,13 @@ async def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_mess async def refund_star_payment(token, user_id, telegram_payment_charge_id): method_url = 'refundStarPayment' payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id} - return await _process_request(token, method_url, params=payload, method='post') + return await _process_request(token, method_url, params=payload) async def unpin_all_general_forum_topic_messages(token, chat_id): method_url = 'unpinAllGeneralForumTopicMessages' payload = {'chat_id': chat_id} - return await _process_request(token, method_url, params=payload, method='post') + return await _process_request(token, method_url, params=payload) # InlineQuery @@ -1812,7 +1814,7 @@ async def create_invoice_link(token, title, description, payload, provider_token need_email=None, need_shipping_address=None, send_phone_number_to_provider=None, send_email_to_provider=None, is_flexible=None): method_url = r'createInvoiceLink' - payload = {'title': title, 'description': description, 'payload': payload, 'provider_token': provider_token, + payload = {'title': title, 'description': description, 'payload': payload, 'currency': currency, 'prices': await _convert_list_json_serializable(prices)} if max_tip_amount: payload['max_tip_amount'] = max_tip_amount @@ -1842,6 +1844,8 @@ async def create_invoice_link(token, title, description, payload, provider_token payload['send_email_to_provider'] = send_email_to_provider if is_flexible is not None: payload['is_flexible'] = is_flexible + if provider_token is not None: + payload['provider_token'] = provider_token return await _process_request(token, method_url, params=payload, method='post') diff --git a/telebot/types.py b/telebot/types.py index 6479f3468..c36cb8131 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -4494,7 +4494,7 @@ def to_dict(self): json_dict['photo_height'] = self.photo_height if self.description: json_dict['description'] = self.description - if self.show_caption_above_media: + if self.show_caption_above_media is not None: json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -4593,7 +4593,7 @@ def to_dict(self): json_dict['gif_duration'] = self.gif_duration if self.thumbnail_mime_type: json_dict['thumbnail_mime_type'] = self.thumbnail_mime_type - if self.show_caption_above_media: + if self.show_caption_above_media is not None: json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -4692,7 +4692,7 @@ def to_dict(self): json_dict['mpeg4_duration '] = self.mpeg4_duration if self.thumbnail_mime_type: json_dict['thumbnail_mime_type'] = self.thumbnail_mime_type - if self.show_caption_above_media: + if self.show_caption_above_media is not None: json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -4790,7 +4790,7 @@ def to_dict(self): json_dict['video_duration'] = self.video_duration if self.description: json_dict['description'] = self.description - if self.show_caption_above_media: + if self.show_caption_above_media is not None: json_dict['show_caption_above_media'] = self.show_caption_above_media return json_dict @@ -5381,7 +5381,7 @@ def to_json(self): json_dict['parse_mode'] = self.parse_mode if self.caption_entities: json_dict['caption_entities'] = MessageEntity.to_list_of_dicts(self.caption_entities) - if self.show_caption_above_media: + if self.show_caption_above_media is not None: json_dict['show_caption_above_media'] = self.show_caption_above_media return json.dumps(json_dict) From eb3b6998c4638394f273ce04620759aac719fc61 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 1 Jun 2024 20:44:07 +0300 Subject: [PATCH 255/480] Bump version to 4.19.0... and fix Bump version to 4.19.0 and fix MessageEntity.to_dict/to_json --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/types.py | 4 ++-- telebot/version.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 7e46d02c3..ec7735312 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.18.1' +release = '4.19.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 7eae1722e..ad0f75a97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.18.1" +version = "4.19.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/types.py b/telebot/types.py index 1a0b1efec..3358965b5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1665,8 +1665,8 @@ def to_dict(self): "offset": self.offset, "length": self.length, "url": self.url, - "user": self.user, - "language": self.language, + "user": self.user.to_dict(), + "language": self.language, "custom_emoji_id": self.custom_emoji_id} diff --git a/telebot/version.py b/telebot/version.py index 830950124..d9652d819 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.18.1' +__version__ = '4.19.0' From 67230b8ed26f14cd3818f18328d953c519cd768b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 2 Jun 2024 21:26:21 +0300 Subject: [PATCH 256/480] Fix MessageEntity.user if None --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 3358965b5..6ec9d8d4d 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1665,7 +1665,7 @@ def to_dict(self): "offset": self.offset, "length": self.length, "url": self.url, - "user": self.user.to_dict(), + "user": self.user.to_dict() if self.user else None, "language": self.language, "custom_emoji_id": self.custom_emoji_id} From 9d9988668d3b186f6257d2ed780bbc711908db79 Mon Sep 17 00:00:00 2001 From: Moshe <62907797+moshe-coh@users.noreply.github.com> Date: Fri, 7 Jun 2024 01:25:39 +0300 Subject: [PATCH 257/480] fixed copy_message in apihelper.py --- telebot/apihelper.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 4d984dcf1..4c642e8f5 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -428,7 +428,7 @@ def forward_message( def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, - reply_parameters=None): + reply_parameters=None, show_caption_above_media=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -449,6 +449,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['protect_content'] = protect_content if message_thread_id is not None: payload['message_thread_id'] = message_thread_id + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload) From a3f7e307b0b9b8a07c637b30f4a4871ab45fd449 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 8 Jun 2024 20:55:10 +0300 Subject: [PATCH 258/480] Bump version for bugfix release --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/__init__.py | 19 ++++++++++--------- telebot/apihelper.py | 8 ++++---- telebot/version.py | 2 +- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index ec7735312..da36cc2fd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.19.0' +release = '4.19.1' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index ad0f75a97..4cc5b3af0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.19.0" +version = "4.19.1" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/__init__.py b/telebot/__init__.py index 99c492954..b70016506 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1874,7 +1874,6 @@ def copy_message( :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` - """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification @@ -1903,7 +1902,8 @@ def copy_message( apihelper.copy_message(self.token, chat_id, from_chat_id, message_id, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, reply_parameters=reply_parameters, show_caption_above_media=show_caption_above_media)) + message_thread_id=message_thread_id, reply_parameters=reply_parameters, + show_caption_above_media=show_caption_above_media)) def delete_message(self, chat_id: Union[int, str], message_id: int, @@ -1950,13 +1950,13 @@ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): :type message_ids: :obj:`list` of :obj:`int` :return: Returns True on success. - """ return apihelper.delete_messages(self.token, chat_id, message_ids) - def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, - message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: + def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], + disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, + protect_content: Optional[bool]=None) -> List[types.MessageID]: """ Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, they are skipped. Service messages and messages with protected content can't be forwarded. Album grouping is kept for forwarded messages. @@ -2237,9 +2237,9 @@ def send_photo( self.token, chat_id, photo, caption=caption, reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, - message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media)) - + message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, + business_connection_id=business_connection_id, message_effect_id=message_effect_id, + show_caption_above_media=show_caption_above_media)) def send_audio( @@ -5540,7 +5540,8 @@ def edit_message_caption( result = apihelper.edit_message_caption( self.token, caption, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup, show_caption_above_media=show_caption_above_media) + parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup, + show_caption_above_media=show_caption_above_media) if type(result) == bool: return result diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 4c642e8f5..cb0c77467 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -487,8 +487,8 @@ def send_photo( caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, - show_caption_above_media=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None, show_caption_above_media=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -717,8 +717,8 @@ def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=Non def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, - message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, - show_caption_above_media=None): + message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, + message_effect_id=None, show_caption_above_media=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None diff --git a/telebot/version.py b/telebot/version.py index d9652d819..248d79ff7 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.19.0' +__version__ = '4.19.1' From 5de4b1758e917cb6604c5795788f1ce29a9e738b Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 10 Jun 2024 19:58:37 +0300 Subject: [PATCH 259/480] UsersShared fix --- telebot/types.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 6ec9d8d4d..768775f5b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9121,13 +9121,8 @@ class UsersShared(JsonDeserializable): :param request_id: Identifier of the request :type request_id: :obj:`int` - :param user_ids: Array of :obj:`types.SharedUser` of the shared users. These numbers may have more than 32 significant bits - and some programming languages may have difficulty/silent defects in interpreting them. - But they have at most 52 significant bits, so 64-bit integers or double-precision float - types are safe for storing these identifiers. The bot may not have access to the users and - could be unable to use these identifiers unless the users are already known to the bot by - some other means. - :type user_ids: :obj:`list` of :obj:`types.SharedUser` + :param users: Information about users shared with the bot + :type users: :obj:`list` of :obj:`types.SharedUser` :return: Instance of the class :rtype: :class:`UsersShared` @@ -9136,20 +9131,23 @@ class UsersShared(JsonDeserializable): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - obj['user_ids'] = [SharedUser.de_json(user) for user in obj['user_ids']] - + obj['users'] = [SharedUser.de_json(user) for user in obj['users']] return cls(**obj) - def __init__(self, request_id, user_ids: SharedUser, **kwargs): + def __init__(self, request_id, users: List[SharedUser], **kwargs): self.request_id = request_id - self.user_ids = user_ids + self.users = users @property def user_id(self): logger.warning('The parameter "user_id" is deprecated, use "user_ids" instead') return None - + + @property + def user_ids(self): + logger.warning('The parameter "user_ids" is deprecated, use "users" instead') + return self.users + class ChatBoostUpdated(JsonDeserializable): """ From 2e32b412ab966a598f53091b7e05cfeb87562d28 Mon Sep 17 00:00:00 2001 From: Dieter van der Westhuizen Date: Fri, 14 Jun 2024 14:23:47 +0200 Subject: [PATCH 260/480] Update README.md Fixed spelling error in Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 770186d5c..5eb40ce3a 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,7 @@ Handle shipping queries `@bot.shipping_query_handler() # <- passes a ShippingQuery type object to your function` #### Pre Checkout Query Handler -Handle pre checkoupt queries +Handle pre checkout queries `@bot.pre_checkout_query_handler() # <- passes a PreCheckoutQuery type object to your function` #### Poll Handler From 6fe6f38c6ea6c44421fb02c066ea4bdd97212114 Mon Sep 17 00:00:00 2001 From: Dieter van der Westhuizen Date: Fri, 14 Jun 2024 14:35:35 +0200 Subject: [PATCH 261/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5eb40ce3a..5d13646bf 100644 --- a/README.md +++ b/README.md @@ -303,7 +303,7 @@ def query_text(inline_query): #### Chosen Inline handler -Use chosen_inline_handler to get chosen_inline_result in telebot. Don't forgot add the /setinlinefeedback +Use chosen_inline_handler to get chosen_inline_result in telebot. Don't forget to add the /setinlinefeedback command for @Botfather. More information : [collecting-feedback](https://core.telegram.org/bots/inline#collecting-feedback) From ab6374ba62bcb5bb388b77b43c74a9edf3d9b487 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 15 Jun 2024 20:21:11 +0500 Subject: [PATCH 262/480] Fix 1: fixed message_thread_id for copy_messages --- telebot/async_telebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index be3135739..4f7593d03 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3440,8 +3440,8 @@ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, """ disable_notification = self.disable_notification if disable_notification is None else disable_notification protect_content = self.protect_content if protect_content is None else protect_content - result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, - protect_content, message_thread_id, remove_caption) + result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, + protect_content, remove_caption) return [types.MessageID.de_json(message_id) for message_id in result] async def send_dice( From bd36b09c5ddb789a5ff6fdbfbb0a41d228928d2d Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 15 Jun 2024 20:24:49 +0500 Subject: [PATCH 263/480] Fix bug in async middlewares --- telebot/async_telebot.py | 1 - 1 file changed, 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 4f7593d03..6a7c5fe08 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -523,7 +523,6 @@ async def _run_middlewares_and_handlers(self, message, handlers, middlewares, up if isinstance(middleware_result, CancelUpdate): return elif isinstance(middleware_result, SkipHandler): - await middleware.post_process(message, data, handler_error) skip_handlers = True if handlers and not(skip_handlers): From 5c50facc066280ee639dbaabce14c238191018cd Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 16 Jun 2024 23:38:05 +0300 Subject: [PATCH 264/480] Bump version for bugfix release --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index da36cc2fd..34f930a66 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.19.1' +release = '4.19.2' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 4cc5b3af0..b43d71dd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.19.1" +version = "4.19.2" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 248d79ff7..405f70f1a 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.19.1' +__version__ = '4.19.2' From 76f8b790e0a685c120558cf0e7463de9a9137cd9 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 18 Jun 2024 16:36:01 +0500 Subject: [PATCH 265/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d13646bf..10694e4b0 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.4! +##

Supported Bot API version: 7.5!

Official documentation

Official ru documentation

From eec78c931b1b0cae506fc467779d1282f1534df1 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 18 Jun 2024 16:52:58 +0500 Subject: [PATCH 266/480] Added the classes StarTransactions, StarTransaction, TransactionPartner and RevenueWithdrawalState, containing information about Telegram Star transactions involving the bot. --- telebot/types.py | 242 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 1438cf762..588e38919 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10005,3 +10005,245 @@ def de_json(cls, json_string): def __init__(self, type, **kwargs): self.type: BackgroundType = type + + +class RevenueWithdrawalState(JsonDeserializable): + """ + This object describes the state of a revenue withdrawal operation. Currently, it can be one of + RevenueWithdrawalStatePending + RevenueWithdrawalStateSucceeded + RevenueWithdrawalStateFailed + + Telegram documentation: https://core.telegram.org/bots/api#revenuewithdrawalstate + + :param type: Type of the state, always “pending” or “succeeded” or “failed” + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`RevenueWithdrawalStatePending` or :class:`RevenueWithdrawalStateSucceeded` or :class:`RevenueWithdrawalStateFailed` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if obj["type"] == "pending": + return RevenueWithdrawalStatePending.de_json(obj) + elif obj["type"] == "succeeded": + return RevenueWithdrawalStateSucceeded.de_json(obj) + elif obj["type"] == "failed": + return RevenueWithdrawalStateFailed.de_json(obj) + return None + + +class RevenueWithdrawalStatePending(RevenueWithdrawalState): + """ + The withdrawal is in progress. + + Telegram documentation: https://core.telegram.org/bots/api#revenuewithdrawalstatepending + + :param type: Type of the state, always “pending” + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`RevenueWithdrawalStatePending` + """ + + def __init__(self, type, **kwargs): + self.type: str = type + + +class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState): + """ + The withdrawal succeeded. + + Telegram documentation: https://core.telegram.org/bots/api#revenuewithdrawalstatesucceeded + + :param type: Type of the state, always “succeeded” + :type type: :obj:`str` + + :param date: Date the withdrawal was completed in Unix time + :type date: :obj:`int` + + :param url: An HTTPS URL that can be used to see transaction details + :type url: :obj:`str` + + :return: Instance of the class + :rtype: :class:`RevenueWithdrawalStateSucceeded` + """ + + def __init__(self, type, date, url, **kwargs): + self.type: str = type + self.date: int = date + self.url: str = url + + +class RevenueWithdrawalStateFailed(RevenueWithdrawalState): + """ + The withdrawal failed and the transaction was refunded. + + Telegram documentation: https://core.telegram.org/bots/api#revenuewithdrawalstatefailed + + :param type: Type of the state, always “failed” + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`RevenueWithdrawalStateFailed` + """ + + def __init__(self, type, **kwargs): + self.type: str = type + + +class TransactionPartner(JsonDeserializable): + """ + This object describes the source of a transaction, or its recipient for outgoing transactions. Currently, it can be one of + TransactionPartnerFragment + TransactionPartnerUser + TransactionPartnerOther + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartner + + :param type: Type of the transaction partner + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerFragment` or :class:`TransactionPartnerUser` or :class:`TransactionPartnerOther` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if obj["type"] == "fragment": + return TransactionPartnerFragment.de_json(obj) + elif obj["type"] == "user": + return TransactionPartnerUser.de_json(obj) + elif obj["type"] == "other": + return TransactionPartnerOther.de_json(obj) + +class TransactionPartnerFragment(TransactionPartner): + """ + Describes a withdrawal transaction with Fragment. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartnerfragment + + :param type: Type of the transaction partner, always “fragment” + :type type: :obj:`str` + + :param withdrawal_state: Optional. State of the transaction if the transaction is outgoing + :type withdrawal_state: :class:`RevenueWithdrawalState` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerFragment` + + """ + + def __init__(self, type, withdrawal_state=None, **kwargs): + self.type: str = type + self.withdrawal_state: Optional[RevenueWithdrawalState] = withdrawal_state + + +class TransactionPartnerUser(TransactionPartner): + """ + Describes a transaction with a user. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartneruser + + :param type: Type of the transaction partner, always “user” + :type type: :obj:`str` + + :param user: Information about the user + :type user: :class:`User` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerUser` + """ + + def __init__(self, type, user, **kwargs): + self.type: str = type + self.user: User = user + +class TransactionPartnerOther(TransactionPartner): + """ + Describes a transaction with an unknown source or recipient. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartnerother + + :param type: Type of the transaction partner, always “other” + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerOther` + """ + + def __init__(self, type, **kwargs): + self.type: str = type + + +class StarTransaction(JsonDeserializable): + """ + Describes a Telegram Star transaction. + + Telegram documentation: https://core.telegram.org/bots/api#startransaction + + :param id: Unique identifier of the transaction. Coincides with the identifer of the original transaction for refund transactions. Coincides with SuccessfulPayment.telegram_payment_charge_id for successful incoming payments from users. + :type id: :obj:`str` + + :param amount: Number of Telegram Stars transferred by the transaction + :type amount: :obj:`int` + + :param date: Date the transaction was created in Unix time + :type date: :obj:`int` + + :param source: Optional. Source of an incoming transaction (e.g., a user purchasing goods or services, Fragment refunding a failed withdrawal). Only for incoming transactions + :type source: :class:`TransactionPartner` + + :param receiver: Optional. Receiver of an outgoing transaction (e.g., a user for a purchase refund, Fragment for a withdrawal). Only for outgoing transactions + :type receiver: :class:`TransactionPartner` + + :return: Instance of the class + :rtype: :class:`StarTransaction` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'source' in obj: + obj['source'] = TransactionPartner.de_json(obj['source']) + if 'receiver' in obj: + obj['receiver'] = TransactionPartner.de_json(obj['receiver']) + return cls(**obj) + + def __init__(self, id, amount, date, source=None, receiver=None, **kwargs): + self.id: str = id + self.amount: int = amount + self.date: int = date + self.source: Optional[TransactionPartner] = source + self.receiver: Optional[TransactionPartner] = receiver + + +class StarTransactions(JsonDeserializable): + """ + Contains a list of Telegram Star transactions. + + Telegram documentation: https://core.telegram.org/bots/api#startransactions + + :param transactions: The list of transactions + :type transactions: :obj:`list` of :class:`StarTransaction` + + :return: Instance of the class + :rtype: :class:`StarTransactions` + + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['transactions'] = [StarTransaction.de_json(transaction) for transaction in obj['transactions']] + return cls(**obj) + + def __init__(self, transactions, **kwargs): + self.transactions: List[StarTransaction] = transactions From dbe9e3232b04242c5da099885d7e3638867a00d1 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 18 Jun 2024 16:59:24 +0500 Subject: [PATCH 267/480] Added the method getStarTransactions that can be used to get the list of all Telegram Star transactions for the bot. --- telebot/__init__.py | 21 +++++++++++++++++++++ telebot/apihelper.py | 10 ++++++++++ telebot/async_telebot.py | 19 +++++++++++++++++++ telebot/asyncio_helper.py | 8 ++++++++ 4 files changed, 58 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index b70016506..b43ea89c8 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5478,6 +5478,27 @@ def answer_pre_checkout_query( """ return apihelper.answer_pre_checkout_query( self.token, pre_checkout_query_id, ok, error_message=error_message) + + + def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int]=None) -> types.StarTransactions: + """ + Returns the bot's Telegram Star transactions in chronological order. On success, returns a StarTransactions object. + + Telegram documentation: https://core.telegram.org/bots/api#getstartransactions + + :param offset: Number of transactions to skip in the response + :type offset: :obj:`int` + + :param limit: The maximum number of transactions to be retrieved. Values between 1-100 are accepted. Defaults to 100. + :type limit: :obj:`int` + + :return: On success, returns a StarTransactions object. + :rtype: :obj:`types.StarTransactions` + """ + return types.StarTransactions.de_json( + apihelper.get_star_transactions(self.token, offset=offset, limit=limit) + ) + def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index cb0c77467..59039ce56 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1667,6 +1667,16 @@ def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_message=No payload['error_message'] = error_message return _make_request(token, method_url, params=payload) +def get_star_transactions(token, offset=None, limit=None): + method_url = 'getStarTransactions' + payload = {} + if offset: + payload['offset'] = offset + if limit: + payload['limit'] = limit + return _make_request(token, method_url, params=payload) + + def refund_star_payment(token, user_id, telegram_payment_charge_id): method_url = 'refundStarPayment' payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 6a7c5fe08..7fe6e48af 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6802,6 +6802,25 @@ async def answer_pre_checkout_query( """ return await asyncio_helper.answer_pre_checkout_query(self.token, pre_checkout_query_id, ok, error_message) + + async def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int]=None) -> types.StarTransactions: + """ + Returns the bot's Telegram Star transactions in chronological order. + + Telegram documentation: https://core.telegram.org/bots/api#getstartransactions + + :param offset: Number of transactions to skip in the response + :type offset: :obj:`int` + + :param limit: The maximum number of transactions to be retrieved. Values between 1-100 are accepted. Defaults to 100. + :type limit: :obj:`int` + + :return: On success, returns a StarTransactions object. + :rtype: :obj:`types.StarTransactions` + """ + + return types.StarTransactions.de_json(await asyncio_helper.get_star_transactions(self.token, offset, limit)) + async def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: """ Refunds a successful payment in Telegram Stars. Returns True on success. diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index e7838fbb4..077ed3e61 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1646,6 +1646,14 @@ async def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_mess payload['error_message'] = error_message return await _process_request(token, method_url, params=payload) +async def get_star_transactions(token, offset=None, limit=None): + method_url = 'getStarTransactions' + payload = {} + if offset: + payload['offset'] = offset + if limit: + payload['limit'] = limit + return await _process_request(token, method_url, params=payload) async def refund_star_payment(token, user_id, telegram_payment_charge_id): method_url = 'refundStarPayment' From 67e2ec5fa0f75c05a1c76552969989aa4cf9d234 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 18 Jun 2024 17:10:46 +0500 Subject: [PATCH 268/480] Added the parameter business_connection_id to the methods editMessageText, editMessageMedia, editMessageCaption, editMessageLiveLocation, stopMessageLiveLocation and editMessageReplyMarkup, allowing the bot to edit business messages. --- telebot/__init__.py | 47 ++++++++++++++++++++++++++++++--------- telebot/apihelper.py | 24 +++++++++++++++----- telebot/async_telebot.py | 46 +++++++++++++++++++++++++++++--------- telebot/asyncio_helper.py | 24 +++++++++++++++----- 4 files changed, 107 insertions(+), 34 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index b43ea89c8..369ce77a3 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3324,6 +3324,7 @@ def edit_message_live_location( heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, live_period: Optional[int]=None, + business_connection_id: Optional[str]=None ) -> types.Message or bool: """ Use this method to edit live location messages. A location can be edited until its live_period expires or editing is explicitly @@ -3366,6 +3367,9 @@ def edit_message_live_location( :param live_period: New period in seconds during which the location can be updated, starting from the message send date. If 0x7FFFFFFF is specified, then the location can be updated forever. Otherwise, the new value must not exceed the current live_period by more than a day, and the live location expiration date must remain within the next 90 days. If not specified, then live_period remains unchanged :type live_period: :obj:`int` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. :rtype: :class:`telebot.types.Message` or bool """ @@ -3373,7 +3377,7 @@ def edit_message_live_location( apihelper.edit_message_live_location( self.token, latitude, longitude, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, reply_markup=reply_markup, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, - proximity_alert_radius=proximity_alert_radius, live_period=live_period) + proximity_alert_radius=proximity_alert_radius, live_period=live_period, business_connection_id=business_connection_id) ) @@ -3382,7 +3386,8 @@ def stop_message_live_location( message_id: Optional[int]=None, inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - timeout: Optional[int]=None) -> types.Message or bool: + timeout: Optional[int]=None, + business_connection_id: Optional[str]=None) -> types.Message or bool: """ Use this method to stop updating a live location message before live_period expires. On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. @@ -3405,13 +3410,16 @@ def stop_message_live_location( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` + :param business_connection_id: Identifier of a business connection + :type business_connection_id: :obj:`str` + :return: On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. :rtype: :class:`telebot.types.Message` or bool """ return types.Message.de_json( apihelper.stop_message_live_location( self.token, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - reply_markup=reply_markup, timeout=timeout) + reply_markup=reply_markup, timeout=timeout, business_connection_id=business_connection_id) ) @@ -4645,7 +4653,8 @@ def edit_message_text( entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[types.InlineKeyboardMarkup]=None, - link_preview_options : Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]: + link_preview_options : Optional[types.LinkPreviewOptions]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit text and game messages. @@ -4678,6 +4687,9 @@ def edit_message_text( :param link_preview_options: A JSON-serialized object for options used to automatically generate previews for links. :type link_preview_options: :obj:`LinkPreviewOptions` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ @@ -4704,7 +4716,8 @@ def edit_message_text( result = apihelper.edit_message_text( self.token, text, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - parse_mode=parse_mode, entities=entities, reply_markup=reply_markup, link_preview_options=link_preview_options) + parse_mode=parse_mode, entities=entities, reply_markup=reply_markup, link_preview_options=link_preview_options, + business_connection_id=business_connection_id) if type(result) == bool: # if edit inline message return is bool not Message. return result @@ -4715,7 +4728,8 @@ def edit_message_media( self, media: Any, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. @@ -4738,12 +4752,15 @@ def edit_message_media( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`telebot.types.InlineKeyboardMarkup` or :obj:`ReplyKeyboardMarkup` or :obj:`ReplyKeyboardRemove` or :obj:`ForceReply` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ result = apihelper.edit_message_media( self.token, media, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - reply_markup=reply_markup) + reply_markup=reply_markup, business_connection_id=business_connection_id) if type(result) == bool: # if edit inline message return is bool not Message. return result @@ -4754,7 +4771,8 @@ def edit_message_reply_markup( self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit only the reply markup of messages. @@ -4772,12 +4790,15 @@ def edit_message_reply_markup( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`InlineKeyboardMarkup` or :obj:`ReplyKeyboardMarkup` or :obj:`ReplyKeyboardRemove` or :obj:`ForceReply` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ result = apihelper.edit_message_reply_markup( self.token, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - reply_markup=reply_markup) + reply_markup=reply_markup, business_connection_id=business_connection_id) if type(result) == bool: return result @@ -5524,7 +5545,8 @@ def edit_message_caption( parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - show_caption_above_media: Optional[bool]=None) -> Union[types.Message, bool]: + show_caption_above_media: Optional[bool]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit captions of messages. @@ -5554,6 +5576,9 @@ def edit_message_caption( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + :param business_connection_id: Identifier of the business connection to use for the message + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` | :obj:`bool` """ @@ -5562,7 +5587,7 @@ def edit_message_caption( result = apihelper.edit_message_caption( self.token, caption, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup, - show_caption_above_media=show_caption_above_media) + show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id) if type(result) == bool: return result diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 59039ce56..3d5d89bf4 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -594,7 +594,7 @@ def send_location( def edit_message_live_location( token, latitude, longitude, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, - timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, live_period=None): + timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, live_period=None, business_connection_id=None): method_url = r'editMessageLiveLocation' payload = {'latitude': latitude, 'longitude': longitude} if chat_id: @@ -615,12 +615,14 @@ def edit_message_live_location( payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) def stop_message_live_location( token, chat_id=None, message_id=None, - inline_message_id=None, reply_markup=None, timeout=None): + inline_message_id=None, reply_markup=None, timeout=None, business_connection_id=None): method_url = r'stopMessageLiveLocation' payload = {} if chat_id: @@ -633,6 +635,8 @@ def stop_message_live_location( payload['reply_markup'] = _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) @@ -1379,7 +1383,7 @@ def unpin_all_chat_messages(token, chat_id): # Updating messages def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, - entities = None, reply_markup=None, link_preview_options=None): + entities = None, reply_markup=None, link_preview_options=None, business_connection_id=None): method_url = r'editMessageText' payload = {'text': text} if chat_id: @@ -1396,11 +1400,13 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message payload['reply_markup'] = _convert_markup(reply_markup) if link_preview_options is not None: payload['link_preview_options'] = link_preview_options.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None, - parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None): + parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None, business_connection_id=None): method_url = r'editMessageCaption' payload = {'caption': caption} if chat_id: @@ -1417,10 +1423,12 @@ def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_m payload['reply_markup'] = _convert_markup(reply_markup) if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') -def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None): +def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): method_url = r'editMessageMedia' media_json, file = convert_input_media(media) payload = {'media': media_json} @@ -1432,10 +1440,12 @@ def edit_message_media(token, media, chat_id=None, message_id=None, inline_messa payload['inline_message_id'] = inline_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, files=file, method='post' if file else 'get') -def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None): +def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): method_url = r'editMessageReplyMarkup' payload = {} if chat_id: @@ -1446,6 +1456,8 @@ def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_messa payload['inline_message_id'] = inline_message_id if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 7fe6e48af..a6517a7c7 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4724,6 +4724,7 @@ async def edit_message_live_location( heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, live_period: Optional[int]=None, + business_connection_id: Optional[str]=None ) -> types.Message: """ Use this method to edit live location messages. A location can be edited until its live_period expires or editing is explicitly @@ -4766,6 +4767,9 @@ async def edit_message_live_location( :param live_period: New period in seconds during which the location can be updated, starting from the message send date. If 0x7FFFFFFF is specified, then the location can be updated forever. Otherwise, the new value must not exceed the current live_period by more than a day, and the live location expiration date must remain within the next 90 days. If not specified, then live_period remains unchanged :type live_period: :obj:`int` + :param business_connection_id: Identifier of a business connection, in which the message will be edited + :type business_connection_id: :obj:`str` + :return: On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. :rtype: :class:`telebot.types.Message` or bool """ @@ -4773,7 +4777,7 @@ async def edit_message_live_location( await asyncio_helper.edit_message_live_location( self.token, latitude, longitude, chat_id, message_id, inline_message_id, reply_markup, timeout, - horizontal_accuracy, heading, proximity_alert_radius, live_period=live_period) + horizontal_accuracy, heading, proximity_alert_radius, live_period=live_period, business_connection_id=business_connection_id) ) async def stop_message_live_location( @@ -4781,7 +4785,8 @@ async def stop_message_live_location( message_id: Optional[int]=None, inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - timeout: Optional[int]=None) -> types.Message: + timeout: Optional[int]=None, + business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to stop updating a live location message before live_period expires. On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. @@ -4804,12 +4809,15 @@ async def stop_message_live_location( :param timeout: Timeout in seconds for the request. :type timeout: :obj:`int` + :param business_connection_id: Identifier of a business connection, in which the message will be edited + :type business_connection_id: :obj:`str` + :return: On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. :rtype: :class:`telebot.types.Message` or bool """ return types.Message.de_json( await asyncio_helper.stop_message_live_location( - self.token, chat_id, message_id, inline_message_id, reply_markup, timeout)) + self.token, chat_id, message_id, inline_message_id, reply_markup, timeout, business_connection_id)) async def send_venue( self, chat_id: Union[int, str], @@ -6000,7 +6008,8 @@ async def edit_message_text( entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - link_preview_options: Optional[types.LinkPreviewOptions]=None) -> Union[types.Message, bool]: + link_preview_options: Optional[types.LinkPreviewOptions]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit text and game messages. @@ -6033,6 +6042,9 @@ async def edit_message_text( :param link_preview_options: A JSON-serialized object for options used to automatically generate Telegram link previews for messages. :type link_preview_options: :obj:`LinkPreviewOptions` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ @@ -6058,7 +6070,7 @@ async def edit_message_text( link_preview_options = types.LinkPreviewOptions(is_disabled=self.disable_web_page_preview) result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, - entities, reply_markup, link_preview_options) + entities, reply_markup, link_preview_options, business_connection_id) if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -6067,7 +6079,8 @@ async def edit_message_media( self, media: Any, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. @@ -6090,10 +6103,13 @@ async def edit_message_media( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`telebot.types.InlineKeyboardMarkup` or :obj:`ReplyKeyboardMarkup` or :obj:`ReplyKeyboardRemove` or :obj:`ForceReply` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = await asyncio_helper.edit_message_media(self.token, media, chat_id, message_id, inline_message_id, reply_markup) + result = await asyncio_helper.edit_message_media(self.token, media, chat_id, message_id, inline_message_id, reply_markup, business_connection_id) if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -6102,7 +6118,8 @@ async def edit_message_reply_markup( self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> Union[types.Message, bool]: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit only the reply markup of messages. @@ -6120,10 +6137,13 @@ async def edit_message_reply_markup( :param reply_markup: A JSON-serialized object for an inline keyboard. :type reply_markup: :obj:`InlineKeyboardMarkup` or :obj:`ReplyKeyboardMarkup` or :obj:`ReplyKeyboardRemove` or :obj:`ForceReply` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = await asyncio_helper.edit_message_reply_markup(self.token, chat_id, message_id, inline_message_id, reply_markup) + result = await asyncio_helper.edit_message_reply_markup(self.token, chat_id, message_id, inline_message_id, reply_markup, business_connection_id) if type(result) == bool: return result return types.Message.de_json(result) @@ -6845,7 +6865,8 @@ async def edit_message_caption( parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - show_caption_above_media: Optional[bool]=None) -> Union[types.Message, bool]: + show_caption_above_media: Optional[bool]=None, + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to edit captions of messages. @@ -6875,13 +6896,16 @@ async def edit_message_caption( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + :param business_connection_id: Identifier of the business connection to send the message through + :type business_connection_id: :obj:`str` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` | :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode result = await asyncio_helper.edit_message_caption(self.token, caption, chat_id, message_id, inline_message_id, - parse_mode, caption_entities, reply_markup, show_caption_above_media=show_caption_above_media) + parse_mode, caption_entities, reply_markup, show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id) if type(result) == bool: return result return types.Message.de_json(result) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 077ed3e61..0d09a052a 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -580,7 +580,7 @@ async def send_location( async def edit_message_live_location( token, latitude, longitude, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, - timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, live_period=None): + timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, live_period=None, business_connection_id=None): method_url = r'editMessageLiveLocation' payload = {'latitude': latitude, 'longitude': longitude} if chat_id: @@ -601,12 +601,14 @@ async def edit_message_live_location( payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) async def stop_message_live_location( token, chat_id=None, message_id=None, - inline_message_id=None, reply_markup=None, timeout=None): + inline_message_id=None, reply_markup=None, timeout=None, business_connection_id=None): method_url = r'stopMessageLiveLocation' payload = {} if chat_id: @@ -619,6 +621,8 @@ async def stop_message_live_location( payload['reply_markup'] = await _convert_markup(reply_markup) if timeout: payload['timeout'] = timeout + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) @@ -1357,7 +1361,7 @@ async def unpin_all_chat_messages(token, chat_id): # Updating messages async def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, - entities = None, reply_markup=None, link_preview_options=None): + entities = None, reply_markup=None, link_preview_options=None, business_connection_id=None): method_url = r'editMessageText' payload = {'text': text} if chat_id: @@ -1374,11 +1378,13 @@ async def edit_message_text(token, text, chat_id=None, message_id=None, inline_m payload['reply_markup'] = await _convert_markup(reply_markup) if link_preview_options is not None: payload['link_preview_options'] = link_preview_options.to_json() + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, method='post') async def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None, - parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None): + parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None, business_connection_id=None): method_url = r'editMessageCaption' payload = {'caption': caption} if chat_id: @@ -1395,10 +1401,12 @@ async def edit_message_caption(token, caption, chat_id=None, message_id=None, in payload['reply_markup'] = await _convert_markup(reply_markup) if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, method='post') -async def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None): +async def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): method_url = r'editMessageMedia' media_json, file = await convert_input_media(media) payload = {'media': media_json} @@ -1410,10 +1418,12 @@ async def edit_message_media(token, media, chat_id=None, message_id=None, inline payload['inline_message_id'] = inline_message_id if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, files=file, method='post' if file else 'get') -async def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None): +async def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): method_url = r'editMessageReplyMarkup' payload = {} if chat_id: @@ -1424,6 +1434,8 @@ async def edit_message_reply_markup(token, chat_id=None, message_id=None, inline payload['inline_message_id'] = inline_message_id if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, method='post') From c7130d5572128fa35a7f94c9bf8406466ae2f348 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 18 Jun 2024 17:12:38 +0500 Subject: [PATCH 269/480] Added the parameter business_connection_id to the method stopPoll, allowing the bot to stop polls it sent on behalf of a business account. --- telebot/__init__.py | 8 ++++++-- telebot/apihelper.py | 4 +++- telebot/async_telebot.py | 8 ++++++-- telebot/asyncio_helper.py | 4 +++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 369ce77a3..07cda06ae 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5418,7 +5418,8 @@ def send_poll( def stop_poll( self, chat_id: Union[int, str], message_id: int, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> types.Poll: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + business_connection_id: Optional[str]=None) -> types.Poll: """ Use this method to stop a poll which was sent by the bot. On success, the stopped Poll is returned. @@ -5433,11 +5434,14 @@ def stop_poll( :param reply_markup: A JSON-serialized object for a new message markup. :type reply_markup: :obj:`InlineKeyboardMarkup` + :param business_connection_id: Identifier of the business connection to use for the poll + :type business_connection_id: :obj:`str` + :return: On success, the stopped Poll is returned. :rtype: :obj:`types.Poll` """ return types.Poll.de_json( - apihelper.stop_poll(self.token, chat_id, message_id, reply_markup=reply_markup) + apihelper.stop_poll(self.token, chat_id, message_id, reply_markup=reply_markup, business_connection_id=business_connection_id) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 3d5d89bf4..d6a372cba 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1997,11 +1997,13 @@ def get_forum_topic_icon_stickers(token): method_url = r'getForumTopicIconStickers' return _make_request(token, method_url) -def stop_poll(token, chat_id, message_id, reply_markup=None): +def stop_poll(token, chat_id, message_id, reply_markup=None, business_connection_id=None): method_url = r'stopPoll' payload = {'chat_id': str(chat_id), 'message_id': message_id} if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload) def edit_general_forum_topic(token, chat_id, name): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index a6517a7c7..af677e5ef 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6746,7 +6746,8 @@ async def send_poll( async def stop_poll( self, chat_id: Union[int, str], message_id: int, - reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> types.Poll: + reply_markup: Optional[types.InlineKeyboardMarkup]=None, + business_connection_id: Optional[str]=None) -> types.Poll: """ Use this method to stop a poll which was sent by the bot. On success, the stopped Poll is returned. @@ -6761,10 +6762,13 @@ async def stop_poll( :param reply_markup: A JSON-serialized object for a new message markup. :type reply_markup: :obj:`InlineKeyboardMarkup` + :param business_connection_id: Identifier of the business connection to send the message through + :type business_connection_id: :obj:`str` + :return: On success, the stopped Poll is returned. :rtype: :obj:`types.Poll` """ - return types.Poll.de_json(await asyncio_helper.stop_poll(self.token, chat_id, message_id, reply_markup)) + return types.Poll.de_json(await asyncio_helper.stop_poll(self.token, chat_id, message_id, reply_markup, business_connection_id)) async def answer_shipping_query( self, shipping_query_id: str, ok: bool, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 0d09a052a..ef755630f 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2084,11 +2084,13 @@ def wrapper(key, val): return wrapper -async def stop_poll(token, chat_id, message_id, reply_markup=None): +async def stop_poll(token, chat_id, message_id, reply_markup=None, business_connection_id=None): method_url = r'stopPoll' payload = {'chat_id': str(chat_id), 'message_id': message_id} if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload) # exceptions From e256a716965ca13a77d6805a842e7d07417bc48d Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 20 Jun 2024 20:05:31 +0500 Subject: [PATCH 270/480] Added de_json classes for types --- telebot/types.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index fe92a6ff0..5d69af0ff 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10123,6 +10123,12 @@ class RevenueWithdrawalStatePending(RevenueWithdrawalState): def __init__(self, type, **kwargs): self.type: str = type + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState): """ @@ -10148,6 +10154,13 @@ def __init__(self, type, date, url, **kwargs): self.date: int = date self.url: str = url + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + class RevenueWithdrawalStateFailed(RevenueWithdrawalState): """ @@ -10165,6 +10178,12 @@ class RevenueWithdrawalStateFailed(RevenueWithdrawalState): def __init__(self, type, **kwargs): self.type: str = type + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + class TransactionPartner(JsonDeserializable): """ @@ -10214,6 +10233,15 @@ def __init__(self, type, withdrawal_state=None, **kwargs): self.type: str = type self.withdrawal_state: Optional[RevenueWithdrawalState] = withdrawal_state + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'withdrawal_state' in obj: + obj['withdrawal_state'] = RevenueWithdrawalState.de_json(obj['withdrawal_state']) + return cls(**obj) + + class TransactionPartnerUser(TransactionPartner): """ @@ -10234,6 +10262,14 @@ class TransactionPartnerUser(TransactionPartner): def __init__(self, type, user, **kwargs): self.type: str = type self.user: User = user + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['user'] = User.de_json(obj['user']) + return cls(**obj) + class TransactionPartnerOther(TransactionPartner): """ @@ -10251,6 +10287,13 @@ class TransactionPartnerOther(TransactionPartner): def __init__(self, type, **kwargs): self.type: str = type + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + class StarTransaction(JsonDeserializable): """ From b1166a35af8b2ded26812234e06566da631baebf Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 22 Jun 2024 13:15:33 +0300 Subject: [PATCH 271/480] Bump version to 4.20.0 --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 34f930a66..f2b1deb6b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.19.2' +release = '4.20.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index b43d71dd1..75b695f44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.19.2" +version = "4.20.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 405f70f1a..96c6fbd20 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.19.2' +__version__ = '4.20.0' From 167e602907f72e7b50f24e10647334194b8d6627 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 22 Jun 2024 13:35:03 +0300 Subject: [PATCH 272/480] Add "timeout" parameter to edit_xxx functions --- telebot/__init__.py | 33 +++++++++++++++++++------ telebot/apihelper.py | 27 ++++++++++++++++----- telebot/async_telebot.py | 51 ++++++++++++++++++++++++++++++--------- telebot/asyncio_helper.py | 27 ++++++++++++++++----- 4 files changed, 106 insertions(+), 32 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 07cda06ae..4100e26a0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4654,7 +4654,8 @@ def edit_message_text( disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility reply_markup: Optional[types.InlineKeyboardMarkup]=None, link_preview_options : Optional[types.LinkPreviewOptions]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit text and game messages. @@ -4690,6 +4691,9 @@ def edit_message_text( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ @@ -4717,7 +4721,7 @@ def edit_message_text( result = apihelper.edit_message_text( self.token, text, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, parse_mode=parse_mode, entities=entities, reply_markup=reply_markup, link_preview_options=link_preview_options, - business_connection_id=business_connection_id) + business_connection_id=business_connection_id, timeout=timeout) if type(result) == bool: # if edit inline message return is bool not Message. return result @@ -4729,7 +4733,8 @@ def edit_message_media( message_id: Optional[int]=None, inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. @@ -4755,12 +4760,15 @@ def edit_message_media( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ result = apihelper.edit_message_media( self.token, media, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - reply_markup=reply_markup, business_connection_id=business_connection_id) + reply_markup=reply_markup, business_connection_id=business_connection_id, timeout=timeout) if type(result) == bool: # if edit inline message return is bool not Message. return result @@ -4772,7 +4780,8 @@ def edit_message_reply_markup( message_id: Optional[int]=None, inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit only the reply markup of messages. @@ -4793,12 +4802,15 @@ def edit_message_reply_markup( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ result = apihelper.edit_message_reply_markup( self.token, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, - reply_markup=reply_markup, business_connection_id=business_connection_id) + reply_markup=reply_markup, business_connection_id=business_connection_id, timeout=timeout) if type(result) == bool: return result @@ -5550,7 +5562,8 @@ def edit_message_caption( caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, show_caption_above_media: Optional[bool]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit captions of messages. @@ -5583,6 +5596,9 @@ def edit_message_caption( :param business_connection_id: Identifier of the business connection to use for the message :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` | :obj:`bool` """ @@ -5591,7 +5607,8 @@ def edit_message_caption( result = apihelper.edit_message_caption( self.token, caption, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, parse_mode=parse_mode, caption_entities=caption_entities, reply_markup=reply_markup, - show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id) + show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id, + timeout=timeout) if type(result) == bool: return result diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d6a372cba..54ce9f691 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1382,8 +1382,9 @@ def unpin_all_chat_messages(token, chat_id): # Updating messages -def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, - entities = None, reply_markup=None, link_preview_options=None, business_connection_id=None): +def edit_message_text( + token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, entities = None, + reply_markup=None, link_preview_options=None, business_connection_id=None, timeout=None): method_url = r'editMessageText' payload = {'text': text} if chat_id: @@ -1402,11 +1403,14 @@ def edit_message_text(token, text, chat_id=None, message_id=None, inline_message payload['link_preview_options'] = link_preview_options.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return _make_request(token, method_url, params=payload, method='post') -def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None, - parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None, business_connection_id=None): +def edit_message_caption( + token, caption, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, caption_entities=None, + reply_markup=None, show_caption_above_media=None, business_connection_id=None, timeout=None): method_url = r'editMessageCaption' payload = {'caption': caption} if chat_id: @@ -1425,10 +1429,14 @@ def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_m payload['show_caption_above_media'] = show_caption_above_media if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return _make_request(token, method_url, params=payload, method='post') -def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): +def edit_message_media( + token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, + business_connection_id=None, timeout=None): method_url = r'editMessageMedia' media_json, file = convert_input_media(media) payload = {'media': media_json} @@ -1442,10 +1450,14 @@ def edit_message_media(token, media, chat_id=None, message_id=None, inline_messa payload['reply_markup'] = _convert_markup(reply_markup) if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return _make_request(token, method_url, params=payload, files=file, method='post' if file else 'get') -def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): +def edit_message_reply_markup( + token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None, + timeout=None): method_url = r'editMessageReplyMarkup' payload = {} if chat_id: @@ -1458,6 +1470,8 @@ def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_messa payload['reply_markup'] = _convert_markup(reply_markup) if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return _make_request(token, method_url, params=payload, method='post') @@ -1590,6 +1604,7 @@ def send_invoice( :param protect_content: Protects the contents of the sent message from forwarding and saving :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only :param reply_parameters: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :return: """ method_url = r'sendInvoice' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index af677e5ef..2a338722a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2362,11 +2362,17 @@ def register_business_message_handler(self, :param callback: function to be called :type callback: :obj:`function` + :param commands: list of commands + :type commands: :obj:`list` of :obj:`str` + + :param regexp: Regular expression + :type regexp: :obj:`str` + :param func: Function executed as a filter :type func: :obj:`function` - :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) - :type pass_bot: :obj:`bool` + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. + :type content_types: :obj:`list` of :obj:`str` :param kwargs: Optional keyword arguments(custom filters) @@ -6009,7 +6015,8 @@ async def edit_message_text( disable_web_page_preview: Optional[bool]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, link_preview_options: Optional[types.LinkPreviewOptions]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit text and game messages. @@ -6045,6 +6052,9 @@ async def edit_message_text( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ @@ -6069,8 +6079,9 @@ async def edit_message_text( # create a LinkPreviewOptions object link_preview_options = types.LinkPreviewOptions(is_disabled=self.disable_web_page_preview) - result = await asyncio_helper.edit_message_text(self.token, text, chat_id, message_id, inline_message_id, parse_mode, - entities, reply_markup, link_preview_options, business_connection_id) + result = await asyncio_helper.edit_message_text( + self.token, text, chat_id, message_id, inline_message_id, parse_mode, entities, reply_markup, + link_preview_options, business_connection_id, timeout) if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -6080,7 +6091,8 @@ async def edit_message_media( message_id: Optional[int]=None, inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message album, then it can be edited only to a photo or a video. @@ -6106,10 +6118,14 @@ async def edit_message_media( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = await asyncio_helper.edit_message_media(self.token, media, chat_id, message_id, inline_message_id, reply_markup, business_connection_id) + result = await asyncio_helper.edit_message_media( + self.token, media, chat_id, message_id, inline_message_id, reply_markup, business_connection_id, timeout) if type(result) == bool: # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -6119,7 +6135,8 @@ async def edit_message_reply_markup( message_id: Optional[int]=None, inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit only the reply markup of messages. @@ -6140,10 +6157,14 @@ async def edit_message_reply_markup( :param business_connection_id: Unique identifier of the business connection :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` or :obj:`bool` """ - result = await asyncio_helper.edit_message_reply_markup(self.token, chat_id, message_id, inline_message_id, reply_markup, business_connection_id) + result = await asyncio_helper.edit_message_reply_markup( + self.token, chat_id, message_id, inline_message_id, reply_markup, business_connection_id, timeout) if type(result) == bool: return result return types.Message.de_json(result) @@ -6870,7 +6891,8 @@ async def edit_message_caption( caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, show_caption_above_media: Optional[bool]=None, - business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: + business_connection_id: Optional[str]=None, + timeout: Optional[int]=None) -> Union[types.Message, bool]: """ Use this method to edit captions of messages. @@ -6903,13 +6925,18 @@ async def edit_message_caption( :param business_connection_id: Identifier of the business connection to send the message through :type business_connection_id: :obj:`str` + :param timeout: Timeout in seconds for the request. + :type timeout: :obj:`int` + :return: On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. :rtype: :obj:`types.Message` | :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode - result = await asyncio_helper.edit_message_caption(self.token, caption, chat_id, message_id, inline_message_id, - parse_mode, caption_entities, reply_markup, show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id) + result = await asyncio_helper.edit_message_caption( + self.token, caption, chat_id, message_id, inline_message_id, parse_mode, caption_entities, reply_markup, + show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id, + timeout=timeout) if type(result) == bool: return result return types.Message.de_json(result) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index ef755630f..0a484f3b4 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1360,8 +1360,9 @@ async def unpin_all_chat_messages(token, chat_id): # Updating messages -async def edit_message_text(token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, - entities = None, reply_markup=None, link_preview_options=None, business_connection_id=None): +async def edit_message_text( + token, text, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, entities = None, + reply_markup=None, link_preview_options=None, business_connection_id=None, timeout=None): method_url = r'editMessageText' payload = {'text': text} if chat_id: @@ -1380,11 +1381,14 @@ async def edit_message_text(token, text, chat_id=None, message_id=None, inline_m payload['link_preview_options'] = link_preview_options.to_json() if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return await _process_request(token, method_url, params=payload, method='post') -async def edit_message_caption(token, caption, chat_id=None, message_id=None, inline_message_id=None, - parse_mode=None, caption_entities=None,reply_markup=None, show_caption_above_media=None, business_connection_id=None): +async def edit_message_caption( + token, caption, chat_id=None, message_id=None, inline_message_id=None, parse_mode=None, caption_entities=None, + reply_markup=None, show_caption_above_media=None, business_connection_id=None, timeout=None): method_url = r'editMessageCaption' payload = {'caption': caption} if chat_id: @@ -1403,10 +1407,14 @@ async def edit_message_caption(token, caption, chat_id=None, message_id=None, in payload['show_caption_above_media'] = show_caption_above_media if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return await _process_request(token, method_url, params=payload, method='post') -async def edit_message_media(token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): +async def edit_message_media( + token, media, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, + business_connection_id=None, timeout=None): method_url = r'editMessageMedia' media_json, file = await convert_input_media(media) payload = {'media': media_json} @@ -1420,10 +1428,14 @@ async def edit_message_media(token, media, chat_id=None, message_id=None, inline payload['reply_markup'] = await _convert_markup(reply_markup) if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return await _process_request(token, method_url, params=payload, files=file, method='post' if file else 'get') -async def edit_message_reply_markup(token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None): +async def edit_message_reply_markup( + token, chat_id=None, message_id=None, inline_message_id=None, reply_markup=None, business_connection_id=None, + timeout=None): method_url = r'editMessageReplyMarkup' payload = {} if chat_id: @@ -1436,6 +1448,8 @@ async def edit_message_reply_markup(token, chat_id=None, message_id=None, inline payload['reply_markup'] = await _convert_markup(reply_markup) if business_connection_id: payload['business_connection_id'] = business_connection_id + if timeout: + payload['timeout'] = timeout return await _process_request(token, method_url, params=payload, method='post') @@ -1569,6 +1583,7 @@ async def send_invoice( :param protect_content: Protects the contents of the sent message from forwarding and saving :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only :param reply_parameters: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :return: """ method_url = r'sendInvoice' From ab2dca8d03abb2f6f5901a99c00dccc38935191e Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 22 Jun 2024 18:01:36 +0500 Subject: [PATCH 273/480] Add pass_bot to register_business_message (#2316) * Fix pass_bot in business message handler register --- telebot/__init__.py | 7 ++++++- telebot/async_telebot.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4100e26a0..d2bcdc307 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -8336,6 +8336,7 @@ def register_business_message_handler(self, regexp: Optional[str]=None, func: Optional[Callable]=None, content_types: Optional[List[str]]=None, + pass_bot: Optional[bool]=False, **kwargs): """ Registers business connection handler. @@ -8355,11 +8356,15 @@ def register_business_message_handler(self, :param content_types: Supported message content types. Must be a list. Defaults to ['text']. :type content_types: :obj:`list` of :obj:`str` + :param pass_bot: True, if bot instance should be passed to handler + :type pass_bot: :obj:`bool` + :param kwargs: Optional keyword arguments(custom filters) :return: None """ - handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, **kwargs) + handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, + pass_bot=pass_bot, **kwargs) self.add_business_message_handler(handler_dict) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 2a338722a..224856416 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2355,6 +2355,7 @@ def register_business_message_handler(self, regexp: Optional[str]=None, func: Optional[Callable]=None, content_types: Optional[List[str]]=None, + pass_bot: Optional[bool]=False, **kwargs): """ Registers business connection handler. @@ -2374,11 +2375,15 @@ def register_business_message_handler(self, :param content_types: Supported message content types. Must be a list. Defaults to ['text']. :type content_types: :obj:`list` of :obj:`str` + :param pass_bot: True, if bot instance should be passed to handler + :type pass_bot: :obj:`bool` + :param kwargs: Optional keyword arguments(custom filters) :return: None """ - handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, **kwargs) + handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, + pass_bot=pass_bot,**kwargs) self.add_business_message_handler(handler_dict) From 1815fa50e22c6087bfad67eccd01a64ce7ff2ea4 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 22 Jun 2024 18:46:47 +0300 Subject: [PATCH 274/480] Pypy 3.8 removed from tests --- .github/workflows/setup_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index 5518ff2f3..670251511 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10'] + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10'] name: ${{ matrix.python-version }} and tests steps: - uses: actions/checkout@v2 From fce1c3d1710dad4e4d2a7f683ac1188116b16372 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 23 Jun 2024 15:34:05 +0500 Subject: [PATCH 275/480] Added statesv2 --- telebot/__init__.py | 113 +++++++++++++++++--- telebot/custom_filters.py | 16 ++- telebot/storage/base_storage.py | 40 ++++++- telebot/storage/memory_storage.py | 168 ++++++++++++++++++++---------- 4 files changed, 263 insertions(+), 74 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d2bcdc307..8fe414252 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -7,7 +7,7 @@ import threading import time import traceback -from typing import Any, Callable, List, Optional, Union +from typing import Any, Callable, List, Optional, Union, Dict # these imports are used to avoid circular import error import telebot.util @@ -168,7 +168,8 @@ def __init__( disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, allow_sending_without_reply: Optional[bool]=None, - colorful_logs: Optional[bool]=False + colorful_logs: Optional[bool]=False, + token_check: Optional[bool]=True ): # update-related @@ -186,6 +187,11 @@ def __init__( self.webhook_listener = None self._user = None + # token check + if token_check: + self._user = self.get_me() + self.bot_id = self._user.id + # logs-related if colorful_logs: try: @@ -280,6 +286,8 @@ def __init__( self.threaded = threaded if self.threaded: self.worker_pool = util.ThreadPool(self, num_threads=num_threads) + + @property def user(self) -> types.User: @@ -6572,7 +6580,9 @@ def setup_middleware(self, middleware: BaseMiddleware): self.middlewares.append(middleware) - def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None) -> None: + def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None) -> None: """ Sets a new state of a user. @@ -6591,14 +6601,29 @@ def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Option :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: None """ if chat_id is None: chat_id = user_id - self.current_states.set_state(chat_id, user_id, state) + if bot_id is None: + bot_id = self.bot_id + self.current_states.set_state( + chat_id=chat_id, user_id=user_id, state=state, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def reset_data(self, user_id: int, chat_id: Optional[int]=None): + def reset_data(self, user_id: int, chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: """ Reset data for a user in chat. @@ -6608,14 +6633,27 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None): :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: None """ if chat_id is None: chat_id = user_id - self.current_states.reset_data(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + self.current_states.reset_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def delete_state(self, user_id: int, chat_id: Optional[int]=None) -> None: + def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: """ Delete the current state of a user. @@ -6629,10 +6667,14 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None) -> None: """ if chat_id is None: chat_id = user_id - self.current_states.delete_state(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + self.current_states.delete_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def retrieve_data(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Any]: + def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Optional[Dict[str, Any]]: """ Returns context manager with data for a user in chat. @@ -6642,15 +6684,30 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None) -> Optional[A :param chat_id: Chat's unique identifier, defaults to user_id :type chat_id: int, optional + :param bot_id: Bot's identifier + :type bot_id: int, optional + + :param business_connection_id: Business identifier + :type business_connection_id: str, optional + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: int, optional + :return: Context manager with data for a user in chat :rtype: Optional[Any] """ if chat_id is None: chat_id = user_id - return self.current_states.get_interactive_data(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + return self.current_states.get_interactive_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id) - def get_state(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Union[int, str, State]]: + def get_state(self, user_id: int, chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Union[int, str]: """ Gets current state of a user. Not recommended to use this method. But it is ok for debugging. @@ -6661,15 +6718,31 @@ def get_state(self, user_id: int, chat_id: Optional[int]=None) -> Optional[Union :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: state of a user :rtype: :obj:`int` or :obj:`str` or :class:`telebot.types.State` """ if chat_id is None: chat_id = user_id - return self.current_states.get_state(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + return self.current_states.get_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs): + def add_data(self, user_id: int, chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None, + **kwargs) -> None: """ Add data to states. @@ -6679,13 +6752,25 @@ def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs): :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :param kwargs: Data to add :return: None """ if chat_id is None: chat_id = user_id + if bot_id is None: + bot_id = self.bot_id for key, value in kwargs.items(): - self.current_states.set_data(chat_id, user_id, key, value) + self.current_states.set_data(chat_id=chat_id, user_id=user_id, key=key, value=value, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) def register_next_step_handler_by_chat_id( diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index d4d4ffeca..41a7c780c 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -7,6 +7,7 @@ + class SimpleCustomFilter(ABC): """ Simple Custom Filter base class. @@ -417,8 +418,6 @@ def check(self, message, text): user_id = message.from_user.id message = message.message - - if isinstance(text, list): new_text = [] @@ -430,7 +429,11 @@ def check(self, message, text): text = text.name if message.chat.type in ['group', 'supergroup']: - group_state = self.bot.current_states.get_state(chat_id, user_id) + group_state = self.bot.current_states.get_state(chat_id=chat_id, user_id=user_id, business_connection_id=message.business_connection_id, bot_id=self.bot._user.id, + message_thread_id=message.message_thread_id) + if group_state is None and not message.is_topic_message: # needed for general topic and group messages + group_state = self.bot.current_states.get_state(chat_id=chat_id, user_id=user_id, business_connection_id=message.business_connection_id, bot_id=self.bot._user.id) + if group_state == text: return True elif type(text) is list and group_state in text: @@ -438,7 +441,12 @@ def check(self, message, text): else: - user_state = self.bot.current_states.get_state(chat_id, user_id) + user_state = self.bot.current_states.get_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=message.business_connection_id, + bot_id=self.bot._user.id + ) if user_state == text: return True elif type(text) is list and user_state in text: diff --git a/telebot/storage/base_storage.py b/telebot/storage/base_storage.py index 92b31ba85..36545a77c 100644 --- a/telebot/storage/base_storage.py +++ b/telebot/storage/base_storage.py @@ -47,22 +47,56 @@ def get_interactive_data(self, chat_id, user_id): def save(self, chat_id, user_id, data): raise NotImplementedError + + def convert_params_to_key( + self, + chat_id: int, + user_id: int, + prefix: str, + separator: str, + business_connection_id: str=None, + message_thread_id: int=None, + bot_id: int=None + ) -> str: + """ + Convert parameters to a key. + """ + params = [prefix] + if bot_id: + params.append(str(bot_id)) + if business_connection_id: + params.append(business_connection_id) + if message_thread_id: + params.append(str(message_thread_id)) + params.append(str(chat_id)) + params.append(str(user_id)) + return separator.join(params) + + + + class StateContext: """ Class for data. """ - def __init__(self , obj, chat_id, user_id) -> None: + def __init__(self , obj, chat_id, user_id, business_connection_id=None, message_thread_id=None, bot_id=None, ): self.obj = obj - self.data = copy.deepcopy(obj.get_data(chat_id, user_id)) + res = obj.get_data(chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id) + self.data = copy.deepcopy(res) self.chat_id = chat_id self.user_id = user_id + self.bot_id = bot_id + self.business_connection_id = business_connection_id + self.message_thread_id = message_thread_id + def __enter__(self): return self.data def __exit__(self, exc_type, exc_val, exc_tb): - return self.obj.save(self.chat_id, self.user_id, self.data) \ No newline at end of file + return self.obj.save(self.chat_id, self.user_id, self.data, self.business_connection_id, self.message_thread_id, self.bot_id) \ No newline at end of file diff --git a/telebot/storage/memory_storage.py b/telebot/storage/memory_storage.py index 7d71c7ccd..fbf9eebda 100644 --- a/telebot/storage/memory_storage.py +++ b/telebot/storage/memory_storage.py @@ -1,69 +1,131 @@ from telebot.storage.base_storage import StateStorageBase, StateContext - +from typing import Optional, Union class StateMemoryStorage(StateStorageBase): - def __init__(self) -> None: - super().__init__() - self.data = {} - # - # {chat_id: {user_id: {'state': None, 'data': {}}, ...}, ...} - - - def set_state(self, chat_id, user_id, state): - if hasattr(state, 'name'): + def __init__(self, + separator: Optional[str]=":", + prefix: Optional[str]="telebot" + ) -> None: + self.separator = separator + self.prefix = prefix + if not self.prefix: + raise ValueError("Prefix cannot be empty") + + self.data = {} # key: telebot:bot_id:business_connection_id:message_thread_id:chat_id:user_id + + def set_state( + self, chat_id: int, user_id: int, state: str, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + + ) -> bool: + if hasattr(state, "name"): state = state.name - if chat_id in self.data: - if user_id in self.data[chat_id]: - self.data[chat_id][user_id]['state'] = state - return True - else: - self.data[chat_id][user_id] = {'state': state, 'data': {}} - return True - self.data[chat_id] = {user_id: {'state': state, 'data': {}}} + + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + if self.data.get(_key) is None: + self.data[_key] = {"state": state, "data": {}} + else: + self.data[_key]["state"] = state + return True - def delete_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - del self.data[chat_id][user_id] - if chat_id == user_id: - del self.data[chat_id] - - return True + def get_state( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> Union[str, None]: - return False + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + if self.data.get(_key) is None: + return None + + return self.data[_key]["state"] - def get_state(self, chat_id, user_id): + def delete_state( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> bool: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + if self.data.get(_key) is None: + return False + + del self.data[_key] + return True + + + def set_data( + self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], + business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None) -> bool: + + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['state'] + if self.data.get(_key) is None: + return False + self.data[_key]["data"][key] = value + return True - return None - def get_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['data'] + + def get_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> dict: - return None + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) - def reset_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'] = {} - return True - return False + return self.data.get(_key, {}).get("data", None) + + def reset_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> bool: + + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) - def set_data(self, chat_id, user_id, key, value): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'][key] = value - return True - raise RuntimeError('chat_id {} and user_id {} does not exist'.format(chat_id, user_id)) + if self.data.get(_key) is None: + return False + self.data[_key]["data"] = {} + return True + + def get_interactive_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> Optional[dict]: + return StateContext( + self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id + ) + + def save( + self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> bool: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, + message_thread_id, bot_id + ) - def get_interactive_data(self, chat_id, user_id): - return StateContext(self, chat_id, user_id) + if self.data.get(_key) is None: + return False + self.data[_key]["data"] = data + return True + + def __str__(self) -> str: + return f"" + + - def save(self, chat_id, user_id, data): - self.data[chat_id][user_id]['data'] = data \ No newline at end of file From 004f7dec172c8fc0854d54f39880b6f6c1b18aca Mon Sep 17 00:00:00 2001 From: Zaid _ Date: Thu, 27 Jun 2024 14:27:10 +0300 Subject: [PATCH 276/480] fix comparing types --- telebot/__init__.py | 10 +++++----- telebot/async_telebot.py | 10 +++++----- telebot/custom_filters.py | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d2bcdc307..408a11902 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4723,7 +4723,7 @@ def edit_message_text( parse_mode=parse_mode, entities=entities, reply_markup=reply_markup, link_preview_options=link_preview_options, business_connection_id=business_connection_id, timeout=timeout) - if type(result) == bool: # if edit inline message return is bool not Message. + if isinstance(result, bool): # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -4770,7 +4770,7 @@ def edit_message_media( self.token, media, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, reply_markup=reply_markup, business_connection_id=business_connection_id, timeout=timeout) - if type(result) == bool: # if edit inline message return is bool not Message. + if isinstance(result, bool): # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -4812,7 +4812,7 @@ def edit_message_reply_markup( self.token, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id, reply_markup=reply_markup, business_connection_id=business_connection_id, timeout=timeout) - if type(result) == bool: + if isinstance(result, bool): return result return types.Message.de_json(result) @@ -4946,7 +4946,7 @@ def set_game_score( self.token, user_id, score, force=force, disable_edit_message=disable_edit_message, chat_id=chat_id, message_id=message_id, inline_message_id=inline_message_id) - if type(result) == bool: + if isinstance(result, bool): return result return types.Message.de_json(result) @@ -5610,7 +5610,7 @@ def edit_message_caption( show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id, timeout=timeout) - if type(result) == bool: + if isinstance(result, bool): return result return types.Message.de_json(result) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 224856416..4ad59c4da 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6087,7 +6087,7 @@ async def edit_message_text( result = await asyncio_helper.edit_message_text( self.token, text, chat_id, message_id, inline_message_id, parse_mode, entities, reply_markup, link_preview_options, business_connection_id, timeout) - if type(result) == bool: # if edit inline message return is bool not Message. + if isinstance(result, bool): # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -6131,7 +6131,7 @@ async def edit_message_media( """ result = await asyncio_helper.edit_message_media( self.token, media, chat_id, message_id, inline_message_id, reply_markup, business_connection_id, timeout) - if type(result) == bool: # if edit inline message return is bool not Message. + if isinstance(result, bool): # if edit inline message return is bool not Message. return result return types.Message.de_json(result) @@ -6170,7 +6170,7 @@ async def edit_message_reply_markup( """ result = await asyncio_helper.edit_message_reply_markup( self.token, chat_id, message_id, inline_message_id, reply_markup, business_connection_id, timeout) - if type(result) == bool: + if isinstance(result, bool): return result return types.Message.de_json(result) @@ -6298,7 +6298,7 @@ async def set_game_score( """ result = await asyncio_helper.set_game_score(self.token, user_id, score, force, disable_edit_message, chat_id, message_id, inline_message_id) - if type(result) == bool: + if isinstance(result, bool): return result return types.Message.de_json(result) @@ -6942,7 +6942,7 @@ async def edit_message_caption( self.token, caption, chat_id, message_id, inline_message_id, parse_mode, caption_entities, reply_markup, show_caption_above_media=show_caption_above_media, business_connection_id=business_connection_id, timeout=timeout) - if type(result) == bool: + if isinstance(result, bool): return result return types.Message.de_json(result) diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index d4d4ffeca..0c4ca614e 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -215,7 +215,7 @@ def check(self, message, text): """ if isinstance(text, TextFilter): return text.check(message) - elif type(text) is list: + elif isinstance(text, list): return message.text in text else: return text == message.text @@ -353,7 +353,7 @@ def check(self, message, text): """ :meta private: """ - if type(text) is list: + if isinstance(text, list): return message.from_user.language_code in text else: return message.from_user.language_code == text @@ -433,7 +433,7 @@ def check(self, message, text): group_state = self.bot.current_states.get_state(chat_id, user_id) if group_state == text: return True - elif type(text) is list and group_state in text: + elif isinstance(text, list) and group_state in text: return True @@ -441,7 +441,7 @@ def check(self, message, text): user_state = self.bot.current_states.get_state(chat_id, user_id) if user_state == text: return True - elif type(text) is list and user_state in text: + elif isinstance(text, list) and user_state in text: return True From 9feb9be827837e3641e27738c7526c799d263c91 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 22:28:30 +0500 Subject: [PATCH 277/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 10694e4b0..22be0a24c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.5! +##

Supported Bot API version: 7.6!

Official documentation

Official ru documentation

From 915b90fd24c82f7b1b65acfcb2b0300c59a6db3b Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 22:36:41 +0500 Subject: [PATCH 278/480] Added the classes PaidMedia, PaidMediaInfo, PaidMediaPreview, PaidMediaPhoto and PaidMediaVideo, containing information about paid media. --- telebot/types.py | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 5d69af0ff..b17ae48cb 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10361,3 +10361,122 @@ def de_json(cls, json_string): def __init__(self, transactions, **kwargs): self.transactions: List[StarTransaction] = transactions + + +class PaidMedia(JsonDeserializable): + """ + This object describes paid media. Currently, it can be one of + + PaidMediaPreview + PaidMediaPhoto + PaidMediaVideo + + Telegram documentation: https://core.telegram.org/bots/api#paidmedia + + :return: Instance of the class + :rtype: :class:`PaidMediaPreview` or :class:`PaidMediaPhoto` or :class:`PaidMediaVideo` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if obj["type"] == "preview": + return PaidMediaPreview.de_json(obj) + elif obj["type"] == "photo": + return PaidMediaPhoto.de_json(obj) + elif obj["type"] == "video": + return PaidMediaVideo.de_json(obj) + +class PaidMediaPreview(PaidMedia): + """ + The paid media isn't available before the payment. + + Telegram documentation: https://core.telegram.org/bots/api#paidmediapreview + + :param type: Type of the paid media, always “preview” + :type type: :obj:`str` + + :param width: Optional. Media width as defined by the sender + :type width: :obj:`int` + + :param height: Optional. Media height as defined by the sender + :type height: :obj:`int` + + :param duration: Optional. Duration of the media in seconds as defined by the sender + :type duration: :obj:`int` + + :return: Instance of the class + :rtype: :class:`PaidMediaPreview` + """ + + def __init__(self, type, width=None, height=None, duration=None, **kwargs): + self.type: str = type + self.width: Optional[int] = width + self.height: Optional[int] = height + self.duration: Optional[int] = duration + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + +class PaidMediaPhoto(PaidMedia): + """ + The paid media is a photo. + + Telegram documentation: https://core.telegram.org/bots/api#paidmediaphoto + + :param type: Type of the paid media, always “photo” + :type type: :obj:`str` + + :param photo: The photo + :type photo: :obj:`list` of :class:`PhotoSize` + + :return: Instance of the class + :rtype: :class:`PaidMediaPhoto` + + """ + + def __init__(self, type, photo, **kwargs): + self.type: str = type + self.photo: List[PhotoSize] = photo + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + + obj['photo'] = [PhotoSize.de_json(photo) for photo in obj['photo']] + return cls(**obj) + + +class PaidMediaVideo(PaidMedia): + """ + The paid media is a video. + + Telegram documentation: https://core.telegram.org/bots/api#paidmediavideo + + :param type: Type of the paid media, always “video” + :type type: :obj:`str` + + :param video: The video + :type video: :class:`Video` + + :return: Instance of the class + :rtype: :class:`PaidMediaVideo` + """ + + def __init__(self, type, video, **kwargs): + self.type: str = type + self.video: Video = video + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['video'] = Video.de_json(obj['video']) + return cls(**obj) + \ No newline at end of file From 1d8239bf003afa179368ed04921229024983d8d3 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 22:48:38 +0500 Subject: [PATCH 279/480] Added the method sendPaidMedia and the classes InputPaidMedia, InputPaidMediaPhoto and InputPaidMediaVideo, to support sending paid media. --- telebot/__init__.py | 55 +++++++++++++++++++ telebot/apihelper.py | 28 ++++++++++ telebot/async_telebot.py | 55 +++++++++++++++++++ telebot/asyncio_helper.py | 27 ++++++++++ telebot/types.py | 111 +++++++++++++++++++++++++++++++++++++- 5 files changed, 274 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 408a11902..4d3a7398b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3112,6 +3112,61 @@ def send_video_note( protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id) ) + + def send_paid_media( + self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], + caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, + show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, + protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None) -> types.Message: + """ + Use this method to send paid media to channel chats. On success, the sent Message is returned. + + Telegram documentation: https://core.telegram.org/bots/api#sendpaidmedia + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param star_count: The number of Telegram Stars that must be paid to buy access to the media + :type star_count: :obj:`int` + + :param media: A JSON-serialized array describing the media to be sent; up to 10 items + :type media: :obj:`list` of :class:`telebot.types.InputPaidMedia` + + :param caption: Media caption, 0-1024 characters after entities parsing + :type caption: :obj:`str` + + :param parse_mode: Mode for parsing entities in the media caption + :type parse_mode: :obj:`str` + + :param caption_entities: List of special entities that appear in the caption, which can be specified instead of parse_mode + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :param show_caption_above_media: Pass True, if the caption must be shown above the message media + :type show_caption_above_media: :obj:`bool` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound. + :type disable_notification: :obj:`bool` + + :param protect_content: Protects the contents of the sent message from forwarding and saving + :type protect_content: :obj:`bool` + + :param reply_parameters: Description of the message to reply to + :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` + + :return: On success, the sent Message is returned. + :rtype: :class:`telebot.types.Message` + """ + return types.Message.de_json( + apihelper.send_paid_media( + self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode, + caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, + disable_notification=disable_notification, protect_content=protect_content, + reply_parameters=reply_parameters, reply_markup=reply_markup) + ) def send_media_group( diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 54ce9f691..ad6d593d9 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -525,6 +525,34 @@ def send_photo( if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media return _make_request(token, method_url, params=payload, files=files, method='post') + +def send_paid_media( + token, chat_id, star_count, media, + caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, + disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None): + method_url = r'sendPaidMedia' + media_json, files = convert_input_media_array(media) + payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} + if caption: + payload['caption'] = caption + if parse_mode: + payload['parse_mode'] = parse_mode + if caption_entities: + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if protect_content is not None: + payload['protect_content'] = protect_content + if reply_parameters is not None: + payload['reply_parameters'] = reply_parameters.to_json() + if reply_markup: + payload['reply_markup'] = _convert_markup(reply_markup) + return _make_request( + token, method_url, params=payload, + method='post' if files else 'get', + files=files if files else None) def send_media_group( diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 4ad59c4da..5f424fc72 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4526,6 +4526,61 @@ async def send_video_note( self.token, chat_id, data, duration, length, reply_markup, disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + async def send_paid_media( + self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], + caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, + show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, + protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None) -> types.Message: + """ + Use this method to send paid media to channel chats. On success, the sent Message is returned. + + Telegram documentation: https://core.telegram.org/bots/api#sendpaidmedia + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param star_count: The number of Telegram Stars that must be paid to buy access to the media + :type star_count: :obj:`int` + + :param media: A JSON-serialized array describing the media to be sent; up to 10 items + :type media: :obj:`list` of :class:`telebot.types.InputPaidMedia` + + :param caption: Media caption, 0-1024 characters after entities parsing + :type caption: :obj:`str` + + :param parse_mode: Mode for parsing entities in the media caption + :type parse_mode: :obj:`str` + + :param caption_entities: List of special entities that appear in the caption, which can be specified instead of parse_mode + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :param show_caption_above_media: Pass True, if the caption must be shown above the message media + :type show_caption_above_media: :obj:`bool` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound. + :type disable_notification: :obj:`bool` + + :param protect_content: Protects the contents of the sent message from forwarding and saving + :type protect_content: :obj:`bool` + + :param reply_parameters: Description of the message to reply to + :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` + + :return: On success, the sent Message is returned. + :rtype: :class:`telebot.types.Message` + """ + return types.Message.de_json( + await asyncio_helper.send_paid_media( + self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode, + caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, + disable_notification=disable_notification, protect_content=protect_content, + reply_parameters=reply_parameters, reply_markup=reply_markup) + ) + async def send_media_group( self, chat_id: Union[int, str], media: List[Union[ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 0a484f3b4..b6248e1a1 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -514,6 +514,33 @@ async def send_photo( payload['show_caption_above_media'] = show_caption_above_media return await _process_request(token, method_url, params=payload, files=files, method='post') +async def send_paid_media( + token, chat_id, star_count, media, + caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, + disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None): + method_url = r'sendPaidMedia' + media_json, files = convert_input_media_array(media) + payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} + if caption: + payload['caption'] = caption + if parse_mode: + payload['parse_mode'] = parse_mode + if caption_entities: + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + if show_caption_above_media is not None: + payload['show_caption_above_media'] = show_caption_above_media + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if protect_content is not None: + payload['protect_content'] = protect_content + if reply_parameters is not None: + payload['reply_parameters'] = reply_parameters.to_json() + if reply_markup: + payload['reply_markup'] = _convert_markup(reply_markup) + return await _process_request( + token, method_url, params=payload, + method='post' if files else 'get', + files=files if files else None) async def send_media_group( token, chat_id, media, diff --git a/telebot/types.py b/telebot/types.py index b17ae48cb..e1a7fc933 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10361,7 +10361,7 @@ def de_json(cls, json_string): def __init__(self, transactions, **kwargs): self.transactions: List[StarTransaction] = transactions - + class PaidMedia(JsonDeserializable): """ @@ -10479,4 +10479,111 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['video'] = Video.de_json(obj['video']) return cls(**obj) - \ No newline at end of file + + +class InputPaidMedia(JsonSerializable): + """ + This object describes the paid media to be sent. Currently, it can be one of + InputPaidMediaPhoto + InputPaidMediaVideo + + Telegram documentation: https://core.telegram.org/bots/api#inputpaidmedia + + :return: Instance of the class + :rtype: :class:`InputPaidMediaPhoto` or :class:`InputPaidMediaVideo` + """ + + def __init__(self, type, media, **kwargs): + self.type = type + self.media = media + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = {} + data['type'] = str(self.type) + data['media'] = str(self.media) + return data + +class InputPaidMediaPhoto(InputPaidMedia): + """ + The paid media to send is a photo. + + Telegram documentation: https://core.telegram.org/bots/api#inputpaidmediaphoto + + :param type: Type of the media, must be photo + :type type: :obj:`str` + + :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for + Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data + under name. More information on Sending Files » + :type media: :obj:`str` + + :return: Instance of the class + :rtype: :class:`InputPaidMediaPhoto` + """ + + def __init__(self, media, **kwargs): + super().__init__(type='photo', media=media) + +class InputPaidMediaVideo(InputPaidMedia): + """ + The paid media to send is a video. + + Telegram documentation: https://core.telegram.org/bots/api#inputpaidmediavideo + + :param type: Type of the media, must be video + :type type: :obj:`str` + + :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for + Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data + under name. More information on Sending Files » + :type media: :obj:`str` + + :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. + The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. + Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, + so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . + More information on Sending Files » + :type thumbnail: :class:`InputFile` + + :param width: Optional. Video width + :type width: :obj:`int` + + :param height: Optional. Video height + :type height: :obj:`int` + + :param duration: Optional. Video duration in seconds + :type duration: :obj:`int` + + :param supports_streaming: Optional. Pass True if the uploaded video is suitable for streaming + :type supports_streaming: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`InputPaidMediaVideo` + + """ + + def __init__(self, media, thumbnail=None, width=None, height=None, duration=None, supports_streaming=None, **kwargs): + super().__init__(type='video', media=media) + self.thumbnail = thumbnail + self.width = width + self.height = height + self.duration = duration + self.supports_streaming = supports_streaming + + def to_dict(self): + data = super().to_dict() + if self.thumbnail: + data['thumbnail'] = self.thumbnail.to_dict() + if self.width: + data['width'] = self.width + if self.height: + data['height'] = self.height + if self.duration: + data['duration'] = self.duration + if self.supports_streaming: + data['supports_streaming'] = self.supports_streaming + return data + From ca9ab83091d4f19b0511bb9b6a3df694ab91e0a0 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 22:52:30 +0500 Subject: [PATCH 280/480] Documented that the methods copyMessage and copyMessages cannot be used to copy paid media. --- telebot/__init__.py | 63 +++++++++++++++++++++------------------- telebot/async_telebot.py | 61 ++++++++++++++++++++------------------ 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4d3a7398b..eef715af2 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1822,6 +1822,9 @@ def copy_message( show_caption_above_media: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. + Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. + A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. The method is analogous to the method + forwardMessage, but the copied message doesn't have a link to the original message. Returns the MessageId of the sent message on success. Telegram documentation: https://core.telegram.org/bots/api#copymessage @@ -1999,47 +2002,47 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: - """ - Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. - Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. - A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. - The method is analogous to the method forwardMessages, but the copied messages don't have a link to the original message. - Album grouping is kept for copied messages. On success, an array of MessageId of the sent messages is returned. + """ + Use this method to copy messages of any kind. + If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, + and invoice messages can't be copied. A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. The method is analogous + to the method forwardMessages, but the copied messages don't have a link to the original message. Album grouping is kept for copied messages. On success, an array + of MessageId of the sent messages is returned. - Telegram documentation: https://core.telegram.org/bots/api#copymessages + Telegram documentation: https://core.telegram.org/bots/api#copymessages - :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) - :type chat_id: :obj:`int` or :obj:`str` + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` - :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) - :type from_chat_id: :obj:`int` or :obj:`str` + :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + :type from_chat_id: :obj:`int` or :obj:`str` - :param message_ids: Message identifiers in the chat specified in from_chat_id - :type message_ids: :obj:`list` of :obj:`int` + :param message_ids: Message identifiers in the chat specified in from_chat_id + :type message_ids: :obj:`list` of :obj:`int` - :param disable_notification: Sends the message silently. Users will receive a notification with no sound - :type disable_notification: :obj:`bool` + :param disable_notification: Sends the message silently. Users will receive a notification with no sound + :type disable_notification: :obj:`bool` - :param message_thread_id: Identifier of a message thread, in which the messages will be sent - :type message_thread_id: :obj:`int` + :param message_thread_id: Identifier of a message thread, in which the messages will be sent + :type message_thread_id: :obj:`int` - :param protect_content: Protects the contents of the forwarded message from forwarding and saving - :type protect_content: :obj:`bool` + :param protect_content: Protects the contents of the forwarded message from forwarding and saving + :type protect_content: :obj:`bool` - :param remove_caption: Pass True to copy the messages without their captions - :type remove_caption: :obj:`bool` + :param remove_caption: Pass True to copy the messages without their captions + :type remove_caption: :obj:`bool` - :return: On success, an array of MessageId of the sent messages is returned. - :rtype: :obj:`list` of :class:`telebot.types.MessageID` - """ - disable_notification = self.disable_notification if disable_notification is None else disable_notification - protect_content = self.protect_content if protect_content is None else protect_content + :return: On success, an array of MessageId of the sent messages is returned. + :rtype: :obj:`list` of :class:`telebot.types.MessageID` + """ + disable_notification = self.disable_notification if disable_notification is None else disable_notification + protect_content = self.protect_content if protect_content is None else protect_content - result = apihelper.copy_messages( - self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, - message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) - return [types.MessageID.de_json(message_id) for message_id in result] + result = apihelper.copy_messages( + self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, + message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) + return [types.MessageID.de_json(message_id) for message_id in result] def send_dice( diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 5f424fc72..75ebe6791 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3248,6 +3248,10 @@ async def copy_message( show_caption_above_media: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. + If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, + and invoice messages can't be copied. A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. The method is analogous + to the method forwardMessages, but the copied messages don't have a link to the original message. Album grouping is kept for copied messages. On success, an array + of MessageId of the sent messages is returned. Telegram documentation: https://core.telegram.org/bots/api#copymessage @@ -3415,44 +3419,43 @@ async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[s async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: - """ - Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. - Service messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can be copied - only if the value of the field correct_option_id is known to the bot. The method is analogous to the method forwardMessages, but - the copied messages don't have a link to the original message. Album grouping is kept for copied messages. - On success, an array of MessageId of the sent messages is returned. + """ + Use this method to copy messages of any kind. + Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. + A quiz poll can be copied only if the value of the field correct_option_id is known to the bot. The method is analogous to the method + forwardMessage, but the copied message doesn't have a link to the original message. Returns the MessageId of the sent message on success. - Telegram documentation: https://core.telegram.org/bots/api#copymessages + Telegram documentation: https://core.telegram.org/bots/api#copymessages - :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) - :type chat_id: :obj:`int` or :obj:`str` + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` - :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) - :type from_chat_id: :obj:`int` or :obj:`str` + :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + :type from_chat_id: :obj:`int` or :obj:`str` - :param message_ids: Message identifiers in the chat specified in from_chat_id - :type message_ids: :obj:`list` of :obj:`int` + :param message_ids: Message identifiers in the chat specified in from_chat_id + :type message_ids: :obj:`list` of :obj:`int` - :param disable_notification: Sends the message silently. Users will receive a notification with no sound - :type disable_notification: :obj:`bool` + :param disable_notification: Sends the message silently. Users will receive a notification with no sound + :type disable_notification: :obj:`bool` - :param message_thread_id: Identifier of a message thread, in which the messages will be sent - :type message_thread_id: :obj:`int` + :param message_thread_id: Identifier of a message thread, in which the messages will be sent + :type message_thread_id: :obj:`int` - :param protect_content: Protects the contents of the forwarded message from forwarding and saving - :type protect_content: :obj:`bool` + :param protect_content: Protects the contents of the forwarded message from forwarding and saving + :type protect_content: :obj:`bool` - :param remove_caption: Pass True to copy the messages without their captions - :type remove_caption: :obj:`bool` + :param remove_caption: Pass True to copy the messages without their captions + :type remove_caption: :obj:`bool` - :return: On success, an array of MessageId of the sent messages is returned. - :rtype: :obj:`list` of :class:`telebot.types.MessageID` - """ - disable_notification = self.disable_notification if disable_notification is None else disable_notification - protect_content = self.protect_content if protect_content is None else protect_content - result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, - protect_content, remove_caption) - return [types.MessageID.de_json(message_id) for message_id in result] + :return: On success, an array of MessageId of the sent messages is returned. + :rtype: :obj:`list` of :class:`telebot.types.MessageID` + """ + disable_notification = self.disable_notification if disable_notification is None else disable_notification + protect_content = self.protect_content if protect_content is None else protect_content + result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, + protect_content, remove_caption) + return [types.MessageID.de_json(message_id) for message_id in result] async def send_dice( self, chat_id: Union[int, str], From 01e92b1a49c3441b4c32f5c6b71600809fd1759a Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 22:57:24 +0500 Subject: [PATCH 281/480] Added the field can_send_paid_media to the class ChatFullInfo. --- telebot/types.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index e1a7fc933..51b3f0e56 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -707,6 +707,10 @@ class ChatFullInfo(JsonDeserializable): :param location: Optional. For supergroups, the location to which the supergroup is connected. Returned only in getChat. :type location: :class:`telebot.types.ChatLocation` + :param can_send_paid_media: Optional. True, if paid media messages can be sent or forwarded to the channel chat. + The field is available only for channel chats. + :type can_send_paid_media: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.ChatFullInfo` """ @@ -748,7 +752,8 @@ def __init__(self, id, type, title=None, username=None, first_name=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, - business_opening_hours=None, personal_chat=None, birthdate=None, **kwargs): + business_opening_hours=None, personal_chat=None, birthdate=None, + can_send_paid_media=None, **kwargs): self.id: int = id self.type: str = type self.title: str = title @@ -792,6 +797,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.business_opening_hours: BusinessOpeningHours = business_opening_hours self.personal_chat: Chat = personal_chat self.birthdate: Birthdate = birthdate + self.can_send_paid_media: bool = can_send_paid_media class Chat(ChatFullInfo): From 1d18a2672353e496ed2b23ec7b696b6014382186 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 23:04:44 +0500 Subject: [PATCH 282/480] Added the field paid_media to the classes Message and ExternalReplyInfo. --- telebot/types.py | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 51b3f0e56..728d31167 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -970,6 +970,9 @@ class Message(JsonDeserializable): :param document: Optional. Message is a general file, information about the file :type document: :class:`telebot.types.Document` + :param paid_media: Optional. Message contains paid media; information about the paid media + :type paid_media: :class:`telebot.types.PaidMediaInfo` + :param photo: Optional. Message is a photo, available sizes of the photo :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` @@ -1386,7 +1389,8 @@ def de_json(cls, json_string): opts['effect_id'] = obj['effect_id'] if 'show_caption_above_media' in obj: opts['show_caption_above_media'] = obj['show_caption_above_media'] - + if 'paid_media' in obj: + opts['paid_media'] = PaidMediaInfo.de_json(obj['paid_media']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1497,6 +1501,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.is_from_offline: Optional[bool] = None self.effect_id: Optional[str] = None self.show_caption_above_media: Optional[bool] = None + self.paid_media : Optional[PaidMediaInfo] = None for key in options: setattr(self, key, options[key]) @@ -8517,6 +8522,9 @@ class ExternalReplyInfo(JsonDeserializable): :param document: Optional. Message is a general file, information about the file :type document: :class:`Document` + :param paid_media: Optional. Message is a paid media content + :type paid_media: :class:`PaidMedia` + :param photo: Optional. Message is a photo, available sizes of the photo :type photo: :obj:`list` of :class:`PhotoSize` @@ -8625,7 +8633,7 @@ def __init__( dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None, giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None, location: Optional[Location]=None, poll: Optional[Poll]=None, - venue: Optional[Venue]=None, **kwargs) -> None: + venue: Optional[Venue]=None, paid_media: Optional[PaidMediaInfo]=None, **kwargs) -> None: self.origin: MessageOrigin = origin self.chat: Optional[Chat] = chat self.message_id: Optional[int] = message_id @@ -8649,6 +8657,7 @@ def __init__( self.location: Optional[Location] = location self.poll: Optional[Poll] = poll self.venue: Optional[Venue] = venue + self.paid_media: Optional[PaidMediaInfo] = paid_media # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -10487,6 +10496,34 @@ def de_json(cls, json_string): return cls(**obj) +class PaidMediaInfo(JsonDeserializable): + """ + Describes the paid media added to a message. + + Telegram documentation: https://core.telegram.org/bots/api#paidmediainfo + + :param star_count: The number of Telegram Stars that must be paid to buy access to the media + :type star_count: :obj:`int` + + :param paid_media: Information about the paid media + :type paid_media: :obj:`list` of :class:`PaidMedia` + + :return: Instance of the class + :rtype: :class:`PaidMediaInfo` + """ + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['paid_media'] = [PaidMedia.de_json(media) for media in obj['paid_media']] + return cls(**obj) + + def __init__(self, star_count, paid_media, **kwargs): + self.star_count: int = star_count + self.paid_media: List[PaidMedia] = paid_media + + class InputPaidMedia(JsonSerializable): """ This object describes the paid media to be sent. Currently, it can be one of From 4ec6b402f3e637fb5d91cd8cf75b8e2266b6421e Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 23:07:37 +0500 Subject: [PATCH 283/480] Added the class TransactionPartnerTelegramAds, containing information about Telegram Star transactions involving the Telegram Ads Platform. --- telebot/types.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 728d31167..245f37cd8 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10224,6 +10224,8 @@ def de_json(cls, json_string): return TransactionPartnerFragment.de_json(obj) elif obj["type"] == "user": return TransactionPartnerUser.de_json(obj) + elif obj["type"] == "telegram_ads": + return TransactionPartnerTelegramAds.de_json(obj) elif obj["type"] == "other": return TransactionPartnerOther.de_json(obj) @@ -10285,6 +10287,27 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj['user']) return cls(**obj) +class TransactionPartnerTelegramAds(TransactionPartner): + """ + Describes a transaction with Telegram Ads. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartnertelegramads + + :param type: Type of the transaction partner, always “telegram_ads” + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerTelegramAds` + """ + + def __init__(self, type, **kwargs): + self.type: str = type + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + class TransactionPartnerOther(TransactionPartner): """ @@ -10630,3 +10653,4 @@ def to_dict(self): data['supports_streaming'] = self.supports_streaming return data + \ No newline at end of file From ecde9547aa2d2cd97057f4bc2f85705a1e76f6f6 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 23:12:51 +0500 Subject: [PATCH 284/480] Added the field invoice_payload to the class TransactionPartnerUser, containing the bot-specified invoice payload. --- telebot/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 245f37cd8..9e4cf5f1d 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10272,13 +10272,17 @@ class TransactionPartnerUser(TransactionPartner): :param user: Information about the user :type user: :class:`User` + :param invoice_payload: Optional, Bot-specified invoice payload + :type invoice_payload: :obj:`str` + :return: Instance of the class :rtype: :class:`TransactionPartnerUser` """ - def __init__(self, type, user, **kwargs): + def __init__(self, type, user, invoice_payload=None, **kwargs): self.type: str = type self.user: User = user + self.invoice_payload: Optional[str] = invoice_payload @classmethod def de_json(cls, json_string): From 5117807ea11ae97658dbfba4f772f8685ff58ef8 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Jul 2024 23:13:51 +0500 Subject: [PATCH 285/480] Added support for launching Web Apps via t.me link in the class MenuButtonWebApp. --- telebot/types.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 9e4cf5f1d..2a0bc65d5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7543,7 +7543,9 @@ class MenuButtonWebApp(MenuButton): :type text: :obj:`str` :param web_app: Description of the Web App that will be launched when the user presses the button. The Web App will be - able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. + able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Alternatively, a t.me link + to a Web App of the bot can be specified in the object instead of the Web App's URL, in which case the Web App will be + opened as if the user pressed the link. :type web_app: :class:`telebot.types.WebAppInfo` :return: Instance of the class From f558724c5f117b58bb43656520a48a24c0c3ab37 Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 3 Jul 2024 16:44:30 +0500 Subject: [PATCH 286/480] Error intervals to stop flooding logs & set non_stop to true by default --- telebot/async_telebot.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 4ad59c4da..2f8d0db27 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -246,7 +246,7 @@ def _setup_change_detector(self, path_to_watch: str) -> None: self.event_observer.schedule(self.event_handler, path, recursive=True) self.event_observer.start() - async def polling(self, non_stop: bool=False, skip_pending=False, interval: int=0, timeout: int=20, + async def polling(self, non_stop: bool=True, skip_pending=False, interval: int=0, timeout: int=20, request_timeout: Optional[int]=None, allowed_updates: Optional[List[str]]=None, none_stop: Optional[bool]=None, restart_on_change: Optional[bool]=False, path_to_watch: Optional[str]=None): """ @@ -257,11 +257,6 @@ async def polling(self, non_stop: bool=False, skip_pending=False, interval: int= Always gets updates. - .. note:: - - Set non_stop=True if you want your bot to continue receiving updates - if there is an error. - .. note:: Install watchdog and psutil before using restart_on_change option. @@ -393,6 +388,15 @@ def __hide_token(self, message: str) -> str: return message.replace(code, "*" * len(code)) else: return message + + async def _handle_error_interval(self, error_interval: float): + logger.debug('Waiting for %s seconds before retrying', error_interval) + await asyncio.sleep(error_interval) + if error_interval * 2 < 60: # same logic as sync + error_interval *= 2 + else: + error_interval = 60 + return error_interval async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: int=20, request_timeout: int=None, allowed_updates: Optional[List[str]]=None): @@ -426,16 +430,18 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: self._polling = True + error_interval = 0.25 + try: while self._polling: try: - updates = await self.get_updates(offset=self.offset, allowed_updates=allowed_updates, timeout=timeout, request_timeout=request_timeout) if updates: self.offset = updates[-1].update_id + 1 # noinspection PyAsyncCall asyncio.create_task(self.process_new_updates(updates)) # Seperate task for processing updates if interval: await asyncio.sleep(interval) + error_interval = 0.25 # drop error_interval if no errors except KeyboardInterrupt: return @@ -446,9 +452,10 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', self.__hide_token(str(e))) logger.debug(self.__hide_token(traceback.format_exc())) + error_interval = await self._handle_error_interval(error_interval) if non_stop or handled: - await asyncio.sleep(2) + #await asyncio.sleep(2) # used error_interval instead continue else: return @@ -457,6 +464,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', self.__hide_token(str(e))) logger.debug(self.__hide_token(traceback.format_exc())) + error_interval = await self._handle_error_interval(error_interval) if non_stop or handled: continue @@ -467,6 +475,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) logger.debug(traceback.format_exc()) + error_interval = await self._handle_error_interval(error_interval) if non_stop or handled: continue From 040e23634bc346887e255bf929b4900576a855e9 Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 3 Jul 2024 18:51:11 +0500 Subject: [PATCH 287/480] inputfile fix #2320 --- telebot/__init__.py | 4 ++++ telebot/apihelper.py | 2 +- telebot/async_telebot.py | 4 ++++ telebot/asyncio_helper.py | 2 ++ telebot/types.py | 14 ++++++++++++-- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 408a11902..e1ba557b7 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2598,6 +2598,10 @@ def send_document( logger.warning('The parameter "thumb" is deprecated. Use "thumbnail" instead.') thumbnail = thumb + if isinstance(document, types.InputFile) and visible_file_name: + # inputfile name ignored, warn + logger.warning('Cannot use both InputFile and visible_file_name. InputFile name will be ignored.') + return types.Message.de_json( apihelper.send_data( self.token, chat_id, document, 'document', diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 54ce9f691..a1eb0b221 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -94,7 +94,7 @@ def _make_request(token, method_name, method='get', params=None, files=None): # process types.InputFile for key, value in files_copy.items(): if isinstance(value, types.InputFile): - files[key] = value.file + files[key] = (value.file_name, value.file) elif isinstance(value, tuple) and (len(value) == 2) and isinstance(value[1], types.InputFile): files[key] = (value[0], value[1].file) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 2f8d0db27..ab13b2f60 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4023,6 +4023,10 @@ async def send_document( if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + if isinstance(document, types.InputFile) and visible_file_name: + # inputfile name ignored, warn + logger.warning('Cannot use both InputFile and visible_file_name. InputFile name will be ignored.') + return types.Message.de_json( await asyncio_helper.send_data( self.token, chat_id, document, 'document', diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 0a484f3b4..db0641899 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -130,6 +130,8 @@ def _prepare_data(params=None, files=None): if isinstance(f, tuple): if len(f) == 2: file_name, file = f + if isinstance(file, types.InputFile): + file = file.file else: raise ValueError('Tuple must have exactly 2 elements: filename, fileobj') elif isinstance(f, types.InputFile): diff --git a/telebot/types.py b/telebot/types.py index 5d69af0ff..f8744525e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7735,8 +7735,11 @@ class InputFile: InputFile(pathlib.Path('/path/to/file/file.txt')) ) """ - def __init__(self, file) -> None: - self._file, self.file_name = self._resolve_file(file) + def __init__(self, file: Union[str, IOBase, Path], file_name: Optional[str] = None): + self._file, self._file_name = self._resolve_file(file) + if file_name: + self._file_name = file_name + @staticmethod def _resolve_file(file): @@ -7757,6 +7760,13 @@ def file(self): File object. """ return self._file + + @property + def file_name(self): + """ + File name. + """ + return self._file_name class ForumTopicCreated(JsonDeserializable): From 01f9a28cf156750ff4e636ef1bc8211f6b99f948 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 4 Jul 2024 11:05:03 +0500 Subject: [PATCH 288/480] Fixes from review --- telebot/apihelper.py | 2 +- telebot/asyncio_helper.py | 2 +- telebot/types.py | 20 ++++++++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index ad6d593d9..8c170ec2a 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2145,7 +2145,7 @@ def convert_input_media_array(array): media = [] files = {} for input_media in array: - if isinstance(input_media, types.InputMedia): + if isinstance(input_media, types.InputMedia) or isinstance(input_media, types.InputPaidMedia): media_dict = input_media.to_dict() if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index b6248e1a1..79f09b96b 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2108,7 +2108,7 @@ async def convert_input_media_array(array): media = [] files = {} for input_media in array: - if isinstance(input_media, types.InputMedia): + if isinstance(input_media, types.InputMedia) or isinstance(input_media, types.InputPaidMedia): media_dict = input_media.to_dict() if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') diff --git a/telebot/types.py b/telebot/types.py index 2a0bc65d5..abbc69bbd 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6737,7 +6737,7 @@ def to_dict(self): ret['height'] = self.height if self.duration: ret['duration'] = self.duration - if self.supports_streaming: + if self.supports_streaming is not None: ret['supports_streaming'] = self.supports_streaming if self.has_spoiler is not None: ret['has_spoiler'] = self.has_spoiler @@ -10569,13 +10569,21 @@ def __init__(self, type, media, **kwargs): self.type = type self.media = media + if service_utils.is_string(self.media): + self._media_name = '' + self._media_dic = self.media + else: + self._media_name = service_utils.generate_random_token() + self._media_dic = 'attach://{0}'.format(self._media_name) + def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): - data = {} - data['type'] = str(self.type) - data['media'] = str(self.media) + data = { + 'type': self.type, + 'media': self._media_dic + } return data class InputPaidMediaPhoto(InputPaidMedia): @@ -10648,14 +10656,14 @@ def __init__(self, media, thumbnail=None, width=None, height=None, duration=None def to_dict(self): data = super().to_dict() if self.thumbnail: - data['thumbnail'] = self.thumbnail.to_dict() + data['thumbnail'] = self.thumbnail if self.width: data['width'] = self.width if self.height: data['height'] = self.height if self.duration: data['duration'] = self.duration - if self.supports_streaming: + if self.supports_streaming is not None: data['supports_streaming'] = self.supports_streaming return data From 08c08942451efc4e86a8026572bd2078c986486b Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 4 Jul 2024 23:41:49 +0500 Subject: [PATCH 289/480] Fix --- telebot/async_telebot.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ab13b2f60..1fc13276b 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -452,10 +452,11 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', self.__hide_token(str(e))) logger.debug(self.__hide_token(traceback.format_exc())) + + if non_stop: error_interval = await self._handle_error_interval(error_interval) if non_stop or handled: - #await asyncio.sleep(2) # used error_interval instead continue else: return @@ -464,6 +465,8 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', self.__hide_token(str(e))) logger.debug(self.__hide_token(traceback.format_exc())) + + if non_stop: error_interval = await self._handle_error_interval(error_interval) if non_stop or handled: @@ -475,6 +478,8 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if not handled: logger.error('Unhandled exception (full traceback for debug level): %s', str(e)) logger.debug(traceback.format_exc()) + + if non_stop: error_interval = await self._handle_error_interval(error_interval) if non_stop or handled: From b45edee76e81b425c5919ad3090ad172bc7ff683 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 4 Jul 2024 22:23:00 +0300 Subject: [PATCH 290/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f2b1deb6b..cfa926801 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.20.0' +release = '4.21.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 75b695f44..0095c3f21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.20.0" +version = "4.21.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 96c6fbd20..5016764c6 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.20.0' +__version__ = '4.21.0' From 2d56fa87ee7455c623111a45cb817b987d732e5f Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 7 Jul 2024 18:36:29 +0500 Subject: [PATCH 291/480] bot api 7.7 --- README.md | 2 +- telebot/types.py | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 22be0a24c..36f0e7a43 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.6! +##

Supported Bot API version: 7.6!

Official documentation

Official ru documentation

diff --git a/telebot/types.py b/telebot/types.py index d0d3819bb..05a45f0de 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1080,6 +1080,9 @@ class Message(JsonDeserializable): the payment. More about payments » :type successful_payment: :class:`telebot.types.SuccessfulPayment` + :param refunded_payment: Optional. Message is a service message about a refunded payment, information about the payment. More about payments » + :type refunded_payment: :class:`telebot.types.RefundedPayment` + :param users_shared: Optional. Service message: a user was shared with the bot :type users_shared: :class:`telebot.types.UsersShared` @@ -1391,7 +1394,8 @@ def de_json(cls, json_string): opts['show_caption_above_media'] = obj['show_caption_above_media'] if 'paid_media' in obj: opts['paid_media'] = PaidMediaInfo.de_json(obj['paid_media']) - + if 'refunded_payment' in obj: + opts['refunded_payment'] = RefundedPayment.de_json(obj['refunded_payment']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1502,6 +1506,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.effect_id: Optional[str] = None self.show_caption_above_media: Optional[bool] = None self.paid_media : Optional[PaidMediaInfo] = None + self.refunded_payment : Optional[RefundedPayment] = None for key in options: setattr(self, key, options[key]) @@ -10676,5 +10681,43 @@ def to_dict(self): if self.supports_streaming is not None: data['supports_streaming'] = self.supports_streaming return data + +class RefundedPayment(JsonDeserializable): + """ + This object contains basic information about a refunded payment. + + Telegram documentation: https://core.telegram.org/bots/api#refundedpayment + + :param currency: Three-letter ISO 4217 currency code, or “XTR” for payments in Telegram Stars. Currently, always “XTR” + :type currency: :obj:`str` + + :param total_amount: Total refunded price in the smallest units of the currency (integer, not float/double). For example, for a price of US$ 1.45, total_amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). + :type total_amount: :obj:`int` + + :param invoice_payload: Bot-specified invoice payload + :type invoice_payload: :obj:`str` + + :param telegram_payment_charge_id: Telegram payment identifier + :type telegram_payment_charge_id: :obj:`str` + + :param provider_payment_charge_id: Optional. Provider payment identifier + :type provider_payment_charge_id: :obj:`str` + + :return: Instance of the class + :rtype: :class:`RefundedPayment` + """ + + def __init__(self, currency, total_amount, invoice_payload, telegram_payment_charge_id, provider_payment_charge_id=None, **kwargs): + self.currency: str = currency + self.total_amount: int = total_amount + self.invoice_payload: str = invoice_payload + self.telegram_payment_charge_id: str = telegram_payment_charge_id + self.provider_payment_charge_id: Optional[str] = provider_payment_charge_id + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) \ No newline at end of file From 7e5a044b104527489c84e5579396d24e7c2a8115 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 8 Jul 2024 17:11:37 +0500 Subject: [PATCH 292/480] Sync states v2 early version --- telebot/handler_backends.py | 43 +-------- telebot/states/__init__.py | 43 +++++++++ telebot/states/aio/__init__.py | 0 telebot/states/sync/__init__.py | 7 ++ telebot/states/sync/context.py | 153 ++++++++++++++++++++++++++++++ telebot/states/sync/middleware.py | 17 ++++ 6 files changed, 223 insertions(+), 40 deletions(-) create mode 100644 telebot/states/__init__.py create mode 100644 telebot/states/aio/__init__.py create mode 100644 telebot/states/sync/__init__.py create mode 100644 telebot/states/sync/context.py create mode 100644 telebot/states/sync/middleware.py diff --git a/telebot/handler_backends.py b/telebot/handler_backends.py index b95861e0b..12f8c89bf 100644 --- a/telebot/handler_backends.py +++ b/telebot/handler_backends.py @@ -9,6 +9,8 @@ except: redis_installed = False +# backward compatibility +from telebot.states import State, StatesGroup class HandlerBackend(object): """ @@ -160,45 +162,6 @@ def get_handlers(self, handler_group_id): return handlers -class State: - """ - Class representing a state. - - .. code-block:: python3 - - class MyStates(StatesGroup): - my_state = State() # returns my_state:State string. - """ - def __init__(self) -> None: - self.name = None - def __str__(self) -> str: - return self.name - - -class StatesGroup: - """ - Class representing common states. - - .. code-block:: python3 - - class MyStates(StatesGroup): - my_state = State() # returns my_state:State string. - """ - def __init_subclass__(cls) -> None: - state_list = [] - for name, value in cls.__dict__.items(): - if not name.startswith('__') and not callable(value) and isinstance(value, State): - # change value of that variable - value.name = ':'.join((cls.__name__, name)) - value.group = cls - state_list.append(value) - cls._state_list = state_list - - @classmethod - def state_list(self): - return self._state_list - - class BaseMiddleware: """ Base class for middleware. @@ -292,4 +255,4 @@ def start2(message): """ def __init__(self) -> None: - pass + pass \ No newline at end of file diff --git a/telebot/states/__init__.py b/telebot/states/__init__.py new file mode 100644 index 000000000..0a45f17e1 --- /dev/null +++ b/telebot/states/__init__.py @@ -0,0 +1,43 @@ +""" +Contains classes for states and state groups. +""" + + +class State: + """ + Class representing a state. + + .. code-block:: python3 + + class MyStates(StatesGroup): + my_state = State() # returns my_state:State string. + """ + def __init__(self) -> None: + self.name: str = None + self.group: StatesGroup = None + def __str__(self) -> str: + return f"<{self.group.__name__}:{self.name}>" + + +class StatesGroup: + """ + Class representing common states. + + .. code-block:: python3 + + class MyStates(StatesGroup): + my_state = State() # returns my_state:State string. + """ + def __init_subclass__(cls) -> None: + state_list = [] + for name, value in cls.__dict__.items(): + if not name.startswith('__') and not callable(value) and isinstance(value, State): + # change value of that variable + value.name = ':'.join((cls.__name__, name)) + value.group = cls + state_list.append(value) + cls._state_list = state_list + + @classmethod + def state_list(self): + return self._state_list diff --git a/telebot/states/aio/__init__.py b/telebot/states/aio/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/telebot/states/sync/__init__.py b/telebot/states/sync/__init__.py new file mode 100644 index 000000000..60f9ea2b7 --- /dev/null +++ b/telebot/states/sync/__init__.py @@ -0,0 +1,7 @@ +from .context import StateContext +from .middleware import StateMiddleware + +__all__ = [ + 'StateContext', + 'StateMiddleware', +] \ No newline at end of file diff --git a/telebot/states/sync/context.py b/telebot/states/sync/context.py new file mode 100644 index 000000000..f0a395d01 --- /dev/null +++ b/telebot/states/sync/context.py @@ -0,0 +1,153 @@ +from telebot.states import State, StatesGroup +from telebot.types import CallbackQuery, Message +from telebot import TeleBot + +from typing import Union + + +class StateContext(): + """ + Class representing a state context. + + Passed through a middleware to provide easy way to set states. + + .. code-block:: python3 + + @bot.message_handler(commands=['start']) + def start_ex(message: types.Message, state_context: StateContext): + state_context.set(MyStates.name) + bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) + # also, state_context.data(), .add_data(), .reset_data(), .delete() methods available. + """ + + def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: + self.message: Union[Message, CallbackQuery] = message + self.bot: TeleBot = bot + self.bot_id = self.bot.bot_id + + def _resolve_context(self) -> Union[Message, CallbackQuery]: + chat_id = None + user_id = None + business_connection_id = self.message.business_connection_id + bot_id = self.bot_id + message_thread_id = None + + if isinstance(self.message, Message): + chat_id = self.message.chat.id + user_id = self.message.from_user.id + message_thread_id = self.message.message_thread_id if self.message.is_topic_message else None + elif isinstance(self.message, CallbackQuery): + chat_id = self.message.message.chat.id + user_id = self.message.from_user.id + message_thread_id = self.message.message.message_thread_id if self.message.message.is_topic_message else None + + return chat_id, user_id, business_connection_id, bot_id, message_thread_id + + def set(self, state: Union[State, str]) -> None: + """ + Set state for current user. + + :param state: State object or state name. + :type state: Union[State, str] + + .. code-block:: python3 + + @bot.message_handler(commands=['start']) + def start_ex(message: types.Message, state_context: StateContext): + state_context.set(MyStates.name) + bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + if isinstance(state, State): + state = state.name + return self.bot.set_state( + chat_id=chat_id, + user_id=user_id, + state=state, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + def get(self) -> str: + """ + Get current state for current user. + + :return: Current state name. + :rtype: str + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + return self.bot.get_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + def reset_data(self) -> None: + """ + Reset data for current user. + State will not be changed. + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + return self.bot.reset_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + def delete(self) -> None: + """ + Deletes state and data for current user. + """ + chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + return self.bot.delete_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + def data(self) -> dict: + """ + Get data for current user. + + .. code-block:: python3 + + with state_context.data() as data: + print(data) + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + return self.bot.retrieve_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + def add_data(self, **kwargs) -> None: + """ + Add data for current user. + + :param kwargs: Data to add. + :type kwargs: dict + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + return self.bot.add_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id, + **kwargs + ) \ No newline at end of file diff --git a/telebot/states/sync/middleware.py b/telebot/states/sync/middleware.py new file mode 100644 index 000000000..e1c74cc23 --- /dev/null +++ b/telebot/states/sync/middleware.py @@ -0,0 +1,17 @@ +from telebot.handler_backends import BaseMiddleware +from telebot import TeleBot +from telebot.states.sync.context import StateContext + + +class StateMiddleware(BaseMiddleware): + + def __init__(self, bot: TeleBot) -> None: + self.update_sensitive = False + self.update_types = ['message', 'edited_message', 'callback_query'] #TODO: support other types + self.bot: TeleBot = bot + + def pre_process(self, message, data): + data['state_context'] = StateContext(message, self.bot) + + def post_process(self, message, data, exception): + pass \ No newline at end of file From 4a7bc5d5006b664848feff84b5200c361b3e170b Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 8 Jul 2024 21:47:38 +0500 Subject: [PATCH 293/480] all update types are supported for states(theoretically) --- telebot/custom_filters.py | 48 +++++++++---------------------- telebot/states/__init__.py | 41 +++++++++++++++++++++++++- telebot/states/sync/context.py | 37 +++++++----------------- telebot/states/sync/middleware.py | 6 ++-- tests/test_handler_backends.py | 2 +- 5 files changed, 69 insertions(+), 65 deletions(-) diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index 41a7c780c..1c5bd0b40 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -4,7 +4,7 @@ from telebot import types - +from telebot.states import resolve_context @@ -407,17 +407,7 @@ def check(self, message, text): """ if text == '*': return True - # needs to work with callbackquery - if isinstance(message, types.Message): - chat_id = message.chat.id - user_id = message.from_user.id - - if isinstance(message, types.CallbackQuery): - - chat_id = message.message.chat.id - user_id = message.from_user.id - message = message.message - + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) if isinstance(text, list): new_text = [] @@ -428,29 +418,17 @@ def check(self, message, text): elif isinstance(text, State): text = text.name - if message.chat.type in ['group', 'supergroup']: - group_state = self.bot.current_states.get_state(chat_id=chat_id, user_id=user_id, business_connection_id=message.business_connection_id, bot_id=self.bot._user.id, - message_thread_id=message.message_thread_id) - if group_state is None and not message.is_topic_message: # needed for general topic and group messages - group_state = self.bot.current_states.get_state(chat_id=chat_id, user_id=user_id, business_connection_id=message.business_connection_id, bot_id=self.bot._user.id) - - if group_state == text: - return True - elif type(text) is list and group_state in text: - return True - - - else: - user_state = self.bot.current_states.get_state( - chat_id=chat_id, - user_id=user_id, - business_connection_id=message.business_connection_id, - bot_id=self.bot._user.id - ) - if user_state == text: - return True - elif type(text) is list and user_state in text: - return True + user_state = self.bot.current_states.get_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + if user_state == text: + return True + elif type(text) is list and user_state in text: + return True class IsDigitFilter(SimpleCustomFilter): diff --git a/telebot/states/__init__.py b/telebot/states/__init__.py index 0a45f17e1..b8efe3bbe 100644 --- a/telebot/states/__init__.py +++ b/telebot/states/__init__.py @@ -1,7 +1,7 @@ """ Contains classes for states and state groups. """ - +from telebot import types class State: """ @@ -41,3 +41,42 @@ def __init_subclass__(cls) -> None: @classmethod def state_list(self): return self._state_list + +def resolve_context(message, bot_id: int) -> tuple: + # chat_id, user_id, business_connection_id, bot_id, message_thread_id + + # message, edited_message, channel_post, edited_channel_post, business_message, edited_business_message + if isinstance(message, types.Message): + return (message.chat.id, message.from_user.id, message.business_connection_id, bot_id, + message.message_thread_id if message.is_topic_message else None) + elif isinstance(message, types.CallbackQuery): # callback_query + return (message.message.chat.id, message.from_user.id, message.message.business_connection_id, bot_id, + message.message.message_thread_id if message.message.is_topic_message else None) + elif isinstance(message, types.BusinessConnection): # business_connection + return (message.user_chat_id, message.user.id, message.id, bot_id, None) + elif isinstance(message, types.BusinessMessagesDeleted): # deleted_business_messages + return (message.chat.id, message.chat.id, message.business_connection_id, bot_id, None) + elif isinstance(message, types.MessageReactionUpdated): # message_reaction + return (message.chat.id, message.user.id, None, bot_id, None) + elif isinstance(message, types.MessageReactionCountUpdated): # message_reaction_count + return (message.chat.id, None, None, bot_id, None) + elif isinstance(message, types.InlineQuery): # inline_query + return (None, message.from_user.id, None, bot_id, None) + elif isinstance(message, types.ChosenInlineResult): # chosen_inline_result + return (None, message.from_user.id, None, bot_id, None) + elif isinstance(message, types.ShippingQuery): # shipping_query + return (None, message.from_user.id, None, bot_id, None) + elif isinstance(message, types.PreCheckoutQuery): # pre_checkout_query + return (None, message.from_user.id, None, bot_id, None) + elif isinstance(message, types.PollAnswer): # poll_answer + return (None, message.user.id, None, bot_id, None) + elif isinstance(message, types.ChatMemberUpdated): # chat_member # my_chat_member + return (message.chat.id, message.from_user.id, None, bot_id, None) + elif isinstance(message, types.ChatJoinRequest): # chat_join_request + return (message.chat.id, message.from_user.id, None, bot_id, None) + elif isinstance(message, types.ChatBoostRemoved): # removed_chat_boost + return (message.chat.id, message.source.user.id if message.source else None, None, bot_id, None) + elif isinstance(message, types.ChatBoostUpdated): # chat_boost + return (message.chat.id, message.boost.source.user.id if message.boost.source else None, None, bot_id, None) + else: + pass # not yet supported :( \ No newline at end of file diff --git a/telebot/states/sync/context.py b/telebot/states/sync/context.py index f0a395d01..c8009007a 100644 --- a/telebot/states/sync/context.py +++ b/telebot/states/sync/context.py @@ -1,10 +1,12 @@ from telebot.states import State, StatesGroup from telebot.types import CallbackQuery, Message -from telebot import TeleBot +from telebot import TeleBot, types +from telebot.states import resolve_context from typing import Union + class StateContext(): """ Class representing a state context. @@ -25,24 +27,6 @@ def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: self.bot: TeleBot = bot self.bot_id = self.bot.bot_id - def _resolve_context(self) -> Union[Message, CallbackQuery]: - chat_id = None - user_id = None - business_connection_id = self.message.business_connection_id - bot_id = self.bot_id - message_thread_id = None - - if isinstance(self.message, Message): - chat_id = self.message.chat.id - user_id = self.message.from_user.id - message_thread_id = self.message.message_thread_id if self.message.is_topic_message else None - elif isinstance(self.message, CallbackQuery): - chat_id = self.message.message.chat.id - user_id = self.message.from_user.id - message_thread_id = self.message.message.message_thread_id if self.message.message.is_topic_message else None - - return chat_id, user_id, business_connection_id, bot_id, message_thread_id - def set(self, state: Union[State, str]) -> None: """ Set state for current user. @@ -58,7 +42,7 @@ def start_ex(message: types.Message, state_context: StateContext): bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) if isinstance(state, State): state = state.name return self.bot.set_state( @@ -78,7 +62,7 @@ def get(self) -> str: :rtype: str """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) return self.bot.get_state( chat_id=chat_id, user_id=user_id, @@ -93,7 +77,7 @@ def reset_data(self) -> None: State will not be changed. """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) return self.bot.reset_data( chat_id=chat_id, user_id=user_id, @@ -106,7 +90,7 @@ def delete(self) -> None: """ Deletes state and data for current user. """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) return self.bot.delete_state( chat_id=chat_id, user_id=user_id, @@ -125,7 +109,7 @@ def data(self) -> dict: print(data) """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) return self.bot.retrieve_data( chat_id=chat_id, user_id=user_id, @@ -142,7 +126,7 @@ def add_data(self, **kwargs) -> None: :type kwargs: dict """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = self._resolve_context() + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) return self.bot.add_data( chat_id=chat_id, user_id=user_id, @@ -150,4 +134,5 @@ def add_data(self, **kwargs) -> None: bot_id=bot_id, message_thread_id=message_thread_id, **kwargs - ) \ No newline at end of file + ) + \ No newline at end of file diff --git a/telebot/states/sync/middleware.py b/telebot/states/sync/middleware.py index e1c74cc23..b85f795da 100644 --- a/telebot/states/sync/middleware.py +++ b/telebot/states/sync/middleware.py @@ -1,17 +1,19 @@ from telebot.handler_backends import BaseMiddleware from telebot import TeleBot from telebot.states.sync.context import StateContext +from telebot.util import update_types +from telebot import types class StateMiddleware(BaseMiddleware): def __init__(self, bot: TeleBot) -> None: self.update_sensitive = False - self.update_types = ['message', 'edited_message', 'callback_query'] #TODO: support other types + self.update_types = update_types self.bot: TeleBot = bot def pre_process(self, message, data): data['state_context'] = StateContext(message, self.bot) def post_process(self, message, data, exception): - pass \ No newline at end of file + pass diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index bb541bf8a..f57200c1c 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -19,7 +19,7 @@ @pytest.fixture() def telegram_bot(): - return telebot.TeleBot('', threaded=False) + return telebot.TeleBot('', threaded=False, token_check=False) @pytest.fixture From 805b1669cfe39e6d506dcbc044deef7a2c7399f8 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 8 Jul 2024 22:59:56 +0300 Subject: [PATCH 294/480] Suppress warnings and fix forward_origin --- telebot/custom_filters.py | 4 +--- telebot/types.py | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index 0c4ca614e..a1c0aba14 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -5,8 +5,6 @@ from telebot import types - - class SimpleCustomFilter(ABC): """ Simple Custom Filter base class. @@ -311,7 +309,7 @@ def check(self, message): """ :meta private: """ - return message.forward_date is not None + return message.forward_origin is not None class IsReplyFilter(SimpleCustomFilter): diff --git a/telebot/types.py b/telebot/types.py index 05a45f0de..6913452be 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10111,6 +10111,7 @@ def __init__(self, type, **kwargs): class RevenueWithdrawalState(JsonDeserializable): + # noinspection PyUnresolvedReferences """ This object describes the state of a revenue withdrawal operation. Currently, it can be one of RevenueWithdrawalStatePending @@ -10152,6 +10153,7 @@ class RevenueWithdrawalStatePending(RevenueWithdrawalState): :rtype: :class:`RevenueWithdrawalStatePending` """ + # noinspection PyPackageRequirements def __init__(self, type, **kwargs): self.type: str = type @@ -10181,6 +10183,7 @@ class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState): :rtype: :class:`RevenueWithdrawalStateSucceeded` """ + # noinspection PyPackageRequirements def __init__(self, type, date, url, **kwargs): self.type: str = type self.date: int = date @@ -10207,6 +10210,7 @@ class RevenueWithdrawalStateFailed(RevenueWithdrawalState): :rtype: :class:`RevenueWithdrawalStateFailed` """ + # noinspection PyPackageRequirements def __init__(self, type, **kwargs): self.type: str = type @@ -10218,6 +10222,7 @@ def de_json(cls, json_string): class TransactionPartner(JsonDeserializable): + # noinspection PyUnresolvedReferences """ This object describes the source of a transaction, or its recipient for outgoing transactions. Currently, it can be one of TransactionPartnerFragment @@ -10263,6 +10268,7 @@ class TransactionPartnerFragment(TransactionPartner): """ + # noinspection PyPackageRequirements def __init__(self, type, withdrawal_state=None, **kwargs): self.type: str = type self.withdrawal_state: Optional[RevenueWithdrawalState] = withdrawal_state From 08295ffce73fe6e92a317ce7a30f3905001000ba Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 8 Jul 2024 23:08:12 +0300 Subject: [PATCH 295/480] API version 7.7 in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36f0e7a43..98f8c389a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.6! +##

Supported Bot API version: 7.7!

Official documentation

Official ru documentation

From 73645302fefb828edc35ef4e02e4d78943e80ae3 Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Wed, 10 Jul 2024 16:49:00 +0200 Subject: [PATCH 296/480] Added the ability to make blockquote expandable --- telebot/formatting.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index dd7309416..e536e1bb0 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -341,7 +341,7 @@ def mcite(content: str, escape: Optional[bool]=True) -> str: return content -def hcite(content: str, escape: Optional[bool]=True) -> str: +def hcite(content: str, escape: Optional[bool] = True, expandable: Optional[bool] = False) -> str: """ Returns a html-formatted block-quotation string. @@ -350,11 +350,17 @@ def hcite(content: str, escape: Optional[bool]=True) -> str: :param escape: True if you need to escape special characters. Defaults to True. :type escape: :obj:`bool` - + + :param expandable: True if you need the quote to be expandable. Defaults to False. + :type expandable: :obj:`bool` + :return: The formatted string. :rtype: :obj:`str` """ - return '
{}
'.format(escape_html(content) if escape else content) + return "{}".format( + " expandable" if expandable else "", + escape_html(content) if escape else content, + ) def apply_html_entities(text: str, entities: Optional[List], custom_subs: Optional[Dict[str, str]]) -> str: From 77e3f130936f9e5751ef84018c7b3f7496681c5a Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Wed, 10 Jul 2024 17:47:31 +0200 Subject: [PATCH 297/480] Added the ability to make blockquote expandable --- telebot/formatting.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index 51869a2a0..24299b51a 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -323,7 +323,7 @@ def hide_link(url: str) -> str: return f'' -def mcite(content: str, escape: Optional[bool]=True) -> str: +def mcite(content: str, escape: Optional[bool] = True, expandable: Optional[bool] = False) -> str: """ Returns a Markdown-formatted block-quotation string. @@ -333,11 +333,16 @@ def mcite(content: str, escape: Optional[bool]=True) -> str: :param escape: True if you need to escape special characters. Defaults to True. :type escape: :obj:`bool` + :param expandable: True if you need the quote to be expandable. Defaults to False. + :type expandable: :obj:`bool` + :return: The formatted string. :rtype: :obj:`str` """ content = escape_markdown(content) if escape else content - content = '\n'.join(['>' + line for line in content.split('\n')]) + content = "\n".join([">" + line for line in content.split("\n")]) + if expandable: + return f"**{content}||" return content From c901c75b468c3cbefa6bd2e486c73487c2ce8803 Mon Sep 17 00:00:00 2001 From: Hiddify <114227601+hiddify-com@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:38:53 +0000 Subject: [PATCH 298/480] chg: allow callback_query_handler to do not have func arg. --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 630edb29e..b154d04ca 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -7700,7 +7700,7 @@ def register_chosen_inline_handler(self, callback: Callable, func: Callable, pas self.add_chosen_inline_handler(handler_dict) - def callback_query_handler(self, func, **kwargs): + def callback_query_handler(self, func=None, **kwargs): """ Handles new incoming callback query. As a parameter to the decorator function, it passes :class:`telebot.types.CallbackQuery` object. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d8dd91e05..d50cbf7e0 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -1700,7 +1700,7 @@ def register_chosen_inline_handler(self, callback: Callable[[Any], Awaitable], f handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_chosen_inline_handler(handler_dict) - def callback_query_handler(self, func, **kwargs): + def callback_query_handler(self, func=None, **kwargs): """ Handles new incoming callback query. As a parameter to the decorator function, it passes :class:`telebot.types.CallbackQuery` object. From 676597cf6c8353b4569d17ddc29e235049f05cf7 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 12 Jul 2024 17:16:10 +0500 Subject: [PATCH 299/480] added redis support(not fully tested) --- telebot/custom_filters.py | 4 + telebot/storage/redis_storage.py | 300 ++++++++++++++----------------- 2 files changed, 136 insertions(+), 168 deletions(-) diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index dbba91d9c..e53c669a1 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -407,6 +407,9 @@ def check(self, message, text): chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) + if chat_id is None: + chat_id = user_id # May change in future + if isinstance(text, list): new_text = [] for i in text: @@ -423,6 +426,7 @@ def check(self, message, text): bot_id=bot_id, message_thread_id=message_thread_id ) + if user_state == text: return True elif type(text) is list and user_state in text: diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 3fac57c46..9c52a3fa1 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -1,183 +1,147 @@ -from telebot.storage.base_storage import StateStorageBase, StateContext import json - -redis_installed = True -try: - from redis import Redis, ConnectionPool - -except: - redis_installed = False +import redis +from telebot.storage.base_storage import StateStorageBase, StateContext +from typing import Optional, Union class StateRedisStorage(StateStorageBase): - """ - This class is for Redis storage. - This will work only for states. - To use it, just pass this class to: - TeleBot(storage=StateRedisStorage()) - """ - def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_', redis_url=None): - super().__init__() + def __init__(self, host='localhost', port=6379, db=0, password=None, + prefix='telebot', + redis_url=None, + connection_pool: redis.ConnectionPool=None, + separator: Optional[str]=":", + ) -> None: + self.separator = separator + self.prefix = prefix + if not self.prefix: + raise ValueError("Prefix cannot be empty") + if redis_url: - self.redis = ConnectionPool.from_url(redis_url) + self.redis = redis.Redis.from_url(redis_url) + elif connection_pool: + self.redis = redis.Redis(connection_pool=connection_pool) else: - self.redis = ConnectionPool(host=host, port=port, db=db, password=password) - #self.con = Redis(connection_pool=self.redis) -> use this when necessary - # - # {chat_id: {user_id: {'state': None, 'data': {}}, ...}, ...} - self.prefix = prefix - if not redis_installed: - raise Exception("Redis is not installed. Install it via 'pip install redis'") + self.redis = redis.Redis(host=host, port=port, db=db, password=password) - def get_record(self, key): - """ - Function to get record from database. - It has nothing to do with states. - Made for backward compatibility - """ - connection = Redis(connection_pool=self.redis) - result = connection.get(self.prefix+str(key)) - connection.close() - if result: return json.loads(result) - return - - def set_record(self, key, value): - """ - Function to set record to database. - It has nothing to do with states. - Made for backward compatibility - """ - connection = Redis(connection_pool=self.redis) - connection.set(self.prefix+str(key), json.dumps(value)) - connection.close() + + def set_state( + self, chat_id: int, user_id: int, state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> bool: + if hasattr(state, "name"): + state = state.name + + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + def set_state_action(pipe): + pipe.multi() + #pipe.hset(_key, mapping={"state": state, "data": "{}"}) + pipe.hset(_key, "state", state) + + self.redis.transaction(set_state_action, _key) return True - def delete_record(self, key): - """ - Function to delete record from database. - It has nothing to do with states. - Made for backward compatibility - """ - connection = Redis(connection_pool=self.redis) - connection.delete(self.prefix+str(key)) - connection.close() + def get_state( + self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> Union[str, None]: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + state_bytes = self.redis.hget(_key, "state") + return state_bytes.decode('utf-8') if state_bytes else None + + def delete_state( + self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> bool: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + return self.redis.delete(_key) > 0 + + def set_data( + self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None + ) -> bool: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + def set_data_action(pipe): + pipe.multi() + data = pipe.hget(_key, "data") + data = data.execute()[0] + if data is None: + pipe.hset(_key, "data", json.dumps({key: value})) + else: + data = json.loads(data) + data[key] = value + pipe.hset(_key, "data", json.dumps(data)) + + self.redis.transaction(set_data_action, _key) return True - def set_state(self, chat_id, user_id, state): - """ - Set state for a particular user in a chat. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if hasattr(state, 'name'): - state = state.name + def get_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> dict: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = self.redis.hget(_key, "data") + return json.loads(data) if data else {} + + def reset_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> bool: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + def reset_data_action(pipe): + pipe.multi() + if pipe.exists(_key): + pipe.hset(_key, "data", "{}") + else: + return False + + self.redis.transaction(reset_data_action, _key) + return True - if response: - if user_id in response: - response[user_id]['state'] = state + def get_interactive_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> Optional[dict]: + return StateContext( + self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id + ) + + def save( + self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + ) -> bool: + _key = self.convert_params_to_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, + message_thread_id, bot_id + ) + + def save_action(pipe): + pipe.multi() + if pipe.exists(_key): + pipe.hset(_key, "data", json.dumps(data)) else: - response[user_id] = {'state': state, 'data': {}} - else: - response = {user_id: {'state': state, 'data': {}}} - self.set_record(chat_id, response) + return False + self.redis.transaction(save_action, _key) return True - - def delete_state(self, chat_id, user_id): - """ - Delete state for a particular user in a chat. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - del response[user_id] - if user_id == str(chat_id): - self.delete_record(chat_id) - return True - else: self.set_record(chat_id, response) - return True - return False - - - def get_value(self, chat_id, user_id, key): - """ - Get value for a data of a user in a chat. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - if key in response[user_id]['data']: - return response[user_id]['data'][key] - return None - - def get_state(self, chat_id, user_id): - """ - Get state of a user in a chat. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - return response[user_id]['state'] - - return None - - - def get_data(self, chat_id, user_id): - """ - Get data of particular user in a particular chat. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - return response[user_id]['data'] - return None - - - def reset_data(self, chat_id, user_id): - """ - Reset data of a user in a chat. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - response[user_id]['data'] = {} - self.set_record(chat_id, response) - return True - - - - - def set_data(self, chat_id, user_id, key, value): - """ - Set data without interactive data. - """ - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - response[user_id]['data'][key] = value - self.set_record(chat_id, response) - return True - return False - - def get_interactive_data(self, chat_id, user_id): - """ - Get Data in interactive way. - You can use with() with this function. - """ - return StateContext(self, chat_id, user_id) - - def save(self, chat_id, user_id, data): - response = self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - response[user_id]['data'] = data - self.set_record(chat_id, response) - return True - + def __str__(self) -> str: + keys = self.redis.keys(f"{self.prefix}{self.separator}*") + data = {key.decode(): self.redis.hgetall(key) for key in keys} + return f"" From 5bd42715582f3ebee6edd1da0dccd89dca0b1981 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 12 Jul 2024 17:28:14 +0500 Subject: [PATCH 300/480] Added redis dependency check --- telebot/storage/redis_storage.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 9c52a3fa1..d32ab8f8e 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -1,8 +1,13 @@ import json -import redis from telebot.storage.base_storage import StateStorageBase, StateContext from typing import Optional, Union +redis_installed = True +try: + import redis +except ImportError: + redis_installed = False + class StateRedisStorage(StateStorageBase): def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot', @@ -10,6 +15,10 @@ def __init__(self, host='localhost', port=6379, db=0, password=None, connection_pool: redis.ConnectionPool=None, separator: Optional[str]=":", ) -> None: + + if not redis_installed: + raise ImportError("Redis is not installed. Please install it via pip install redis") + self.separator = separator self.prefix = prefix if not self.prefix: From a79fd77cba36073f7d70bcbff5240c0231ee8f3c Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 12 Jul 2024 17:29:56 +0500 Subject: [PATCH 301/480] fix test --- telebot/storage/redis_storage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index d32ab8f8e..39c75a49b 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -12,7 +12,7 @@ class StateRedisStorage(StateStorageBase): def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot', redis_url=None, - connection_pool: redis.ConnectionPool=None, + connection_pool: 'redis.ConnectionPool'=None, separator: Optional[str]=":", ) -> None: From c29bf0e5358da3b21c519007fea64038745cdd2a Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 12 Jul 2024 21:51:34 +0500 Subject: [PATCH 302/480] Added pickle and renamed method --- telebot/storage/base_storage.py | 2 +- telebot/storage/memory_storage.py | 14 +-- telebot/storage/pickle_storage.py | 195 ++++++++++++++++-------------- telebot/storage/redis_storage.py | 14 +-- 4 files changed, 121 insertions(+), 104 deletions(-) diff --git a/telebot/storage/base_storage.py b/telebot/storage/base_storage.py index 36545a77c..2358e93c9 100644 --- a/telebot/storage/base_storage.py +++ b/telebot/storage/base_storage.py @@ -48,7 +48,7 @@ def get_interactive_data(self, chat_id, user_id): def save(self, chat_id, user_id, data): raise NotImplementedError - def convert_params_to_key( + def _get_key( self, chat_id: int, user_id: int, diff --git a/telebot/storage/memory_storage.py b/telebot/storage/memory_storage.py index fbf9eebda..547445d0c 100644 --- a/telebot/storage/memory_storage.py +++ b/telebot/storage/memory_storage.py @@ -21,7 +21,7 @@ def set_state( if hasattr(state, "name"): state = state.name - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -37,7 +37,7 @@ def get_state( message_thread_id: Optional[int]=None, bot_id: Optional[int]=None ) -> Union[str, None]: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -50,7 +50,7 @@ def delete_state( self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -66,7 +66,7 @@ def set_data( business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -81,7 +81,7 @@ def get_data( message_thread_id: Optional[int]=None, bot_id: Optional[int]=None ) -> dict: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -92,7 +92,7 @@ def reset_data( message_thread_id: Optional[int]=None, bot_id: Optional[int]=None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -114,7 +114,7 @@ def save( self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index 68c9fbed5..64ed7ce85 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -1,34 +1,26 @@ -from telebot.storage.base_storage import StateStorageBase, StateContext import os - import pickle - +import threading +from typing import Optional, Union +from telebot.storage.base_storage import StateStorageBase, StateContext class StatePickleStorage(StateStorageBase): - def __init__(self, file_path="./.state-save/states.pkl") -> None: - super().__init__() + def __init__(self, file_path: str="./.state-save/states.pkl", + prefix='telebot', separator: Optional[str]=":") -> None: self.file_path = file_path + self.prefix = prefix + self.separator = separator + self.lock = threading.Lock() + self.create_dir() - self.data = self.read() - def convert_old_to_new(self): - """ - Use this function to convert old storage to new storage. - This function is for people who was using pickle storage - that was in version <=4.3.1. - """ - # old looks like: - # {1: {'state': 'start', 'data': {'name': 'John'}} - # we should update old version pickle to new. - # new looks like: - # {1: {2: {'state': 'start', 'data': {'name': 'John'}}}} - new_data = {} - for key, value in self.data.items(): - # this returns us id and dict with data and state - new_data[key] = {key: value} # convert this to new - # pass it to global data - self.data = new_data - self.update_data() # update data in file + def _read_from_file(self) -> dict: + with open(self.file_path, 'rb') as f: + return pickle.load(f) + + def _write_to_file(self, data: dict) -> None: + with open(self.file_path, 'wb') as f: + pickle.dump(data, f) def create_dir(self): """ @@ -40,77 +32,102 @@ def create_dir(self): with open(self.file_path,'wb') as file: pickle.dump({}, file) - def read(self): - file = open(self.file_path, 'rb') - data = pickle.load(file) - file.close() - return data - - def update_data(self): - file = open(self.file_path, 'wb+') - pickle.dump(self.data, file, protocol=pickle.HIGHEST_PROTOCOL) - file.close() - - def set_state(self, chat_id, user_id, state): - if hasattr(state, 'name'): - state = state.name - if chat_id in self.data: - if user_id in self.data[chat_id]: - self.data[chat_id][user_id]['state'] = state - self.update_data() - return True + def set_state(self, chat_id: int, user_id: int, state: str, + business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + if _key not in data: + data[_key] = {"state": state, "data": {}} else: - self.data[chat_id][user_id] = {'state': state, 'data': {}} - self.update_data() - return True - self.data[chat_id] = {user_id: {'state': state, 'data': {}}} - self.update_data() + data[_key]["state"] = state + self._write_to_file(data) return True - - def delete_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - del self.data[chat_id][user_id] - if chat_id == user_id: - del self.data[chat_id] - self.update_data() - return True - - return False - - def get_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['state'] - - return None - def get_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['data'] + def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Union[str, None]: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + return data.get(_key, {}).get("state") - return None - - def reset_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'] = {} - self.update_data() + def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + if _key in data: + del data[_key] + self._write_to_file(data) return True - return False + return False - def set_data(self, chat_id, user_id, key, value): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'][key] = value - self.update_data() + def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], + business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + state_data = data.get(_key, {}) + state_data["data"][key] = value + if _key not in data: + data[_key] = {"state": None, "data": state_data} + else: + data[_key]["data"][key] = value + self._write_to_file(data) + return True + + def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> dict: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + return data.get(_key, {}).get("data", {}) + + def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + if _key in data: + data[_key]["data"] = {} + self._write_to_file(data) return True - raise RuntimeError('chat_id {} and user_id {} does not exist'.format(chat_id, user_id)) + return False - def get_interactive_data(self, chat_id, user_id): - return StateContext(self, chat_id, user_id) + def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Optional[dict]: + return StateContext( + self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id + ) - def save(self, chat_id, user_id, data): - self.data[chat_id][user_id]['data'] = data - self.update_data() + def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + with self.lock: + data = self._read_from_file() + data[_key]["data"] = data + self._write_to_file(data) + return True + + def __str__(self) -> str: + with self.lock: + with open(self.file_path, 'rb') as f: + data = pickle.load(f) + return f"" diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 39c75a49b..b16ea3016 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -40,7 +40,7 @@ def set_state( if hasattr(state, "name"): state = state.name - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -56,7 +56,7 @@ def get_state( self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> Union[str, None]: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) state_bytes = self.redis.hget(_key, "state") @@ -66,7 +66,7 @@ def delete_state( self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) return self.redis.delete(_key) > 0 @@ -76,7 +76,7 @@ def set_data( business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -98,7 +98,7 @@ def get_data( self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> dict: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) data = self.redis.hget(_key, "data") @@ -108,7 +108,7 @@ def reset_data( self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) @@ -135,7 +135,7 @@ def save( self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> bool: - _key = self.convert_params_to_key( + _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) From 15bced9b67b27b2c54a44f1f060ac552d141d4ca Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 17 Jul 2024 16:31:24 +0500 Subject: [PATCH 303/480] Fixed bugs, renamed StateContext for retrieve_data to StateDataContext to avoid conflicts, added support of statesv2 to async(only memory storage) --- telebot/__init__.py | 9 +- telebot/async_telebot.py | 137 +++++++++++++++--- telebot/asyncio_filters.py | 44 +++--- telebot/asyncio_handler_backends.py | 41 +----- telebot/asyncio_storage/__init__.py | 4 +- telebot/asyncio_storage/base_storage.py | 55 ++++++- telebot/asyncio_storage/memory_storage.py | 169 +++++++++++++++------- telebot/asyncio_storage/pickle_storage.py | 4 +- telebot/asyncio_storage/redis_storage.py | 4 +- telebot/states/__init__.py | 2 +- telebot/states/aio/__init__.py | 7 + telebot/states/aio/context.py | 138 ++++++++++++++++++ telebot/states/aio/middleware.py | 19 +++ telebot/storage/__init__.py | 4 +- telebot/storage/base_storage.py | 2 +- telebot/storage/memory_storage.py | 4 +- telebot/storage/pickle_storage.py | 4 +- telebot/storage/redis_storage.py | 4 +- 18 files changed, 485 insertions(+), 166 deletions(-) create mode 100644 telebot/states/aio/context.py create mode 100644 telebot/states/aio/middleware.py diff --git a/telebot/__init__.py b/telebot/__init__.py index 31370d3e3..08ae9fc6f 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1180,6 +1180,9 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F if restart_on_change: self._setup_change_detector(path_to_watch) + if not self._user: + self._user = self.get_me() + logger.info('Starting your bot with username: [@%s]', self.user.username) if self.threaded: @@ -6678,7 +6681,7 @@ def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Option chat_id = user_id if bot_id is None: bot_id = self.bot_id - self.current_states.set_state( + return self.current_states.set_state( chat_id=chat_id, user_id=user_id, state=state, bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) @@ -6710,7 +6713,7 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None, chat_id = user_id if bot_id is None: bot_id = self.bot_id - self.current_states.reset_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + return self.current_states.reset_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) @@ -6731,7 +6734,7 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_conne chat_id = user_id if bot_id is None: bot_id = self.bot_id - self.current_states.delete_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + return self.current_states.delete_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d8dd91e05..2d443cb5b 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4,7 +4,7 @@ import logging import re import traceback -from typing import Any, Awaitable, Callable, List, Optional, Union +from typing import Any, Awaitable, Callable, List, Optional, Union, Dict import sys # this imports are used to avoid circular import error @@ -18,7 +18,7 @@ from inspect import signature, iscoroutinefunction -from telebot import util, types, asyncio_helper +from telebot import util, types, asyncio_helper, apihelper # have to use sync import asyncio from telebot import asyncio_filters @@ -117,6 +117,8 @@ class AsyncTeleBot: :param colorful_logs: Outputs colorful logs :type colorful_logs: :obj:`bool`, optional + :param token_check: Check token on start + :type token_check: :obj:`bool`, optional, defaults to True """ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[int]=None, @@ -126,7 +128,8 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, allow_sending_without_reply: Optional[bool]=None, - colorful_logs: Optional[bool]=False) -> None: + colorful_logs: Optional[bool]=False, + token_check: Optional[bool]=True) -> None: # update-related self.token = token @@ -183,6 +186,14 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.middlewares = [] self._user = None # set during polling + self.bot_id = None + + if token_check: + result = apihelper.get_me(token) + self._user = types.User.de_json(result) + self.bot_id = self._user.id + + @property def user(self): @@ -424,7 +435,8 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: # show warning logger.warning("Setting non_stop to False will stop polling on API and system exceptions.") - self._user = await self.get_me() + if not self._user: + self._user = await self.get_me() logger.info('Starting your bot with username: [@%s]', self.user.username) @@ -7831,7 +7843,10 @@ async def get_forum_topic_icon_stickers(self) -> List[types.Sticker]: """ return await asyncio_helper.get_forum_topic_icon_stickers(self.token) - async def set_state(self, user_id: int, state: Union[State, int, str], chat_id: Optional[int]=None): + + async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None) -> None: """ Sets a new state of a user. @@ -7850,13 +7865,29 @@ async def set_state(self, user_id: int, state: Union[State, int, str], chat_id: :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: None """ - if not chat_id: + if chat_id is None: chat_id = user_id - await self.current_states.set_state(chat_id, user_id, state) + if bot_id is None: + bot_id = self.bot_id + return await self.current_states.set_state( + chat_id=chat_id, user_id=user_id, state=state, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) - async def reset_data(self, user_id: int, chat_id: Optional[int]=None): + + async def reset_data(self, user_id: int, chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: """ Reset data for a user in chat. @@ -7866,13 +7897,27 @@ async def reset_data(self, user_id: int, chat_id: Optional[int]=None): :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: None """ if chat_id is None: chat_id = user_id - await self.current_states.reset_data(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + return await self.current_states.reset_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) + - async def delete_state(self, user_id: int, chat_id: Optional[int]=None): + async def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: """ Delete the current state of a user. @@ -7884,11 +7929,16 @@ async def delete_state(self, user_id: int, chat_id: Optional[int]=None): :return: None """ - if not chat_id: + if chat_id is None: chat_id = user_id - await self.current_states.delete_state(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + return await self.current_states.delete_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) + - def retrieve_data(self, user_id: int, chat_id: Optional[int]=None): + def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Optional[Dict[str, Any]]: """ Returns context manager with data for a user in chat. @@ -7898,14 +7948,30 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None): :param chat_id: Chat's unique identifier, defaults to user_id :type chat_id: int, optional + :param bot_id: Bot's identifier + :type bot_id: int, optional + + :param business_connection_id: Business identifier + :type business_connection_id: str, optional + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: int, optional + :return: Context manager with data for a user in chat :rtype: Optional[Any] """ - if not chat_id: + if chat_id is None: chat_id = user_id - return self.current_states.get_interactive_data(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + return self.current_states.get_interactive_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id) + - async def get_state(self, user_id, chat_id: Optional[int]=None): + async def get_state(self, user_id: int, chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Union[int, str]: """ Gets current state of a user. Not recommended to use this method. But it is ok for debugging. @@ -7916,14 +7982,31 @@ async def get_state(self, user_id, chat_id: Optional[int]=None): :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: state of a user :rtype: :obj:`int` or :obj:`str` or :class:`telebot.types.State` """ - if not chat_id: + if chat_id is None: chat_id = user_id - return await self.current_states.get_state(chat_id, user_id) + if bot_id is None: + bot_id = self.bot_id + return await self.current_states.get_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) + - async def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs): + async def add_data(self, user_id: int, chat_id: Optional[int]=None, + business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None, + **kwargs) -> None: """ Add data to states. @@ -7933,10 +8016,22 @@ async def add_data(self, user_id: int, chat_id: Optional[int]=None, **kwargs): :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :param kwargs: Data to add :return: None """ - if not chat_id: + if chat_id is None: chat_id = user_id + if bot_id is None: + bot_id = self.bot_id for key, value in kwargs.items(): - await self.current_states.set_data(chat_id, user_id, key, value) + await self.current_states.set_data(chat_id=chat_id, user_id=user_id, key=key, value=value, bot_id=bot_id, + business_connection_id=business_connection_id, message_thread_id=message_thread_id) diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index da794b77b..389ce1643 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -3,6 +3,7 @@ from telebot.asyncio_handler_backends import State from telebot import types +from telebot.states import resolve_context class SimpleCustomFilter(ABC): @@ -397,18 +398,11 @@ async def check(self, message, text): :meta private: """ if text == '*': return True + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) - # needs to work with callbackquery - if isinstance(message, types.Message): - chat_id = message.chat.id - user_id = message.from_user.id - - if isinstance(message, types.CallbackQuery): - - chat_id = message.message.chat.id - user_id = message.from_user.id - message = message.message - + if chat_id is None: + chat_id = user_id # May change in future if isinstance(text, list): new_text = [] @@ -418,21 +412,19 @@ async def check(self, message, text): text = new_text elif isinstance(text, State): text = text.name - - if message.chat.type in ['group', 'supergroup']: - group_state = await self.bot.current_states.get_state(chat_id, user_id) - if group_state == text: - return True - elif type(text) is list and group_state in text: - return True - - - else: - user_state = await self.bot.current_states.get_state(chat_id, user_id) - if user_state == text: - return True - elif type(text) is list and user_state in text: - return True + + user_state = await self.bot.current_states.get_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + if user_state == text: + return True + elif type(text) is list and user_state in text: + return True class IsDigitFilter(SimpleCustomFilter): diff --git a/telebot/asyncio_handler_backends.py b/telebot/asyncio_handler_backends.py index 0861a9893..6c96cc2d7 100644 --- a/telebot/asyncio_handler_backends.py +++ b/telebot/asyncio_handler_backends.py @@ -1,6 +1,7 @@ """ File with all middleware classes, states. """ +from telebot.states import State, StatesGroup class BaseMiddleware: @@ -48,46 +49,6 @@ async def post_process(self, message, data, exception): raise NotImplementedError -class State: - """ - Class representing a state. - - .. code-block:: python3 - - class MyStates(StatesGroup): - my_state = State() # returns my_state:State string. - """ - def __init__(self) -> None: - self.name = None - - def __str__(self) -> str: - return self.name - - -class StatesGroup: - """ - Class representing common states. - - .. code-block:: python3 - - class MyStates(StatesGroup): - my_state = State() # returns my_state:State string. - """ - def __init_subclass__(cls) -> None: - state_list = [] - for name, value in cls.__dict__.items(): - if not name.startswith('__') and not callable(value) and isinstance(value, State): - # change value of that variable - value.name = ':'.join((cls.__name__, name)) - value.group = cls - state_list.append(value) - cls._state_list = state_list - - @classmethod - def state_list(self): - return self._state_list - - class SkipHandler: """ Class for skipping handlers. diff --git a/telebot/asyncio_storage/__init__.py b/telebot/asyncio_storage/__init__.py index 892f0af94..1f9d51650 100644 --- a/telebot/asyncio_storage/__init__.py +++ b/telebot/asyncio_storage/__init__.py @@ -1,13 +1,13 @@ from telebot.asyncio_storage.memory_storage import StateMemoryStorage from telebot.asyncio_storage.redis_storage import StateRedisStorage from telebot.asyncio_storage.pickle_storage import StatePickleStorage -from telebot.asyncio_storage.base_storage import StateContext,StateStorageBase +from telebot.asyncio_storage.base_storage import StateDataContext, StateStorageBase __all__ = [ - 'StateStorageBase', 'StateContext', + 'StateStorageBase', 'StateDataContext', 'StateMemoryStorage', 'StateRedisStorage', 'StatePickleStorage' ] \ No newline at end of file diff --git a/telebot/asyncio_storage/base_storage.py b/telebot/asyncio_storage/base_storage.py index 38615c4c2..6d06e7bfc 100644 --- a/telebot/asyncio_storage/base_storage.py +++ b/telebot/asyncio_storage/base_storage.py @@ -1,6 +1,5 @@ import copy - class StateStorageBase: def __init__(self) -> None: pass @@ -42,27 +41,67 @@ async def reset_data(self, chat_id, user_id): async def get_state(self, chat_id, user_id): raise NotImplementedError - + + def get_interactive_data(self, chat_id, user_id): + """ + Should be sync, but should provide a context manager + with __aenter__ and __aexit__ methods. + """ + raise NotImplementedError + async def save(self, chat_id, user_id, data): raise NotImplementedError + + def _get_key( + self, + chat_id: int, + user_id: int, + prefix: str, + separator: str, + business_connection_id: str=None, + message_thread_id: int=None, + bot_id: int=None + ) -> str: + """ + Convert parameters to a key. + """ + params = [prefix] + if bot_id: + params.append(str(bot_id)) + if business_connection_id: + params.append(business_connection_id) + if message_thread_id: + params.append(str(message_thread_id)) + params.append(str(chat_id)) + params.append(str(user_id)) + + return separator.join(params) + + + + -class StateContext: +class StateDataContext: """ Class for data. """ - - def __init__(self, obj, chat_id, user_id): + def __init__(self , obj, chat_id, user_id, business_connection_id=None, message_thread_id=None, bot_id=None, ): self.obj = obj self.data = None self.chat_id = chat_id self.user_id = user_id + self.bot_id = bot_id + self.business_connection_id = business_connection_id + self.message_thread_id = message_thread_id + - async def __aenter__(self): - self.data = copy.deepcopy(await self.obj.get_data(self.chat_id, self.user_id)) + data = await self.obj.get_data(chat_id=self.chat_id, user_id=self.user_id, business_connection_id=self.business_connection_id, + message_thread_id=self.message_thread_id, bot_id=self.bot_id) + self.data = copy.deepcopy(data) return self.data async def __aexit__(self, exc_type, exc_val, exc_tb): - return await self.obj.save(self.chat_id, self.user_id, self.data) \ No newline at end of file + return await self.obj.save(self.chat_id, self.user_id, self.data, self.business_connection_id, self.message_thread_id, self.bot_id) \ No newline at end of file diff --git a/telebot/asyncio_storage/memory_storage.py b/telebot/asyncio_storage/memory_storage.py index 45c2ad914..e65ed74d4 100644 --- a/telebot/asyncio_storage/memory_storage.py +++ b/telebot/asyncio_storage/memory_storage.py @@ -1,66 +1,131 @@ -from telebot.asyncio_storage.base_storage import StateStorageBase, StateContext +from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext +from typing import Optional, Union class StateMemoryStorage(StateStorageBase): - def __init__(self) -> None: - self.data = {} - # - # {chat_id: {user_id: {'state': None, 'data': {}}, ...}, ...} - - - async def set_state(self, chat_id, user_id, state): - if hasattr(state, 'name'): + def __init__(self, + separator: Optional[str]=":", + prefix: Optional[str]="telebot" + ) -> None: + self.separator = separator + self.prefix = prefix + if not self.prefix: + raise ValueError("Prefix cannot be empty") + + self.data = {} # key: telebot:bot_id:business_connection_id:message_thread_id:chat_id:user_id + + async def set_state( + self, chat_id: int, user_id: int, state: str, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + + ) -> bool: + if hasattr(state, "name"): state = state.name - if chat_id in self.data: - if user_id in self.data[chat_id]: - self.data[chat_id][user_id]['state'] = state - return True - else: - self.data[chat_id][user_id] = {'state': state, 'data': {}} - return True - self.data[chat_id] = {user_id: {'state': state, 'data': {}}} + + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + if self.data.get(_key) is None: + self.data[_key] = {"state": state, "data": {}} + else: + self.data[_key]["state"] = state + return True - async def delete_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - del self.data[chat_id][user_id] - if chat_id == user_id: - del self.data[chat_id] - - return True + async def get_state( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> Union[str, None]: - return False + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + if self.data.get(_key) is None: + return None + + return self.data[_key]["state"] - async def get_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['state'] + async def delete_state( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + if self.data.get(_key) is None: + return False + + del self.data[_key] + return True + + + async def set_data( + self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], + business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, + bot_id: Optional[int]=None) -> bool: + + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + + if self.data.get(_key) is None: + return False + self.data[_key]["data"][key] = value + return True - return None - async def get_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['data'] + + async def get_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> dict: - return None + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) - async def reset_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'] = {} - return True - return False + return self.data.get(_key, {}).get("data", None) + + async def reset_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> bool: + + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) - async def set_data(self, chat_id, user_id, key, value): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'][key] = value - return True - raise RuntimeError('chat_id {} and user_id {} does not exist'.format(chat_id, user_id)) + if self.data.get(_key) is None: + return False + self.data[_key]["data"] = {} + return True + + def get_interactive_data( + self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> Optional[dict]: + return StateDataContext( + self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id + ) + + async def save( + self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + ) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, + message_thread_id, bot_id + ) - def get_interactive_data(self, chat_id, user_id): - return StateContext(self, chat_id, user_id) + if self.data.get(_key) is None: + return False + self.data[_key]["data"] = data + return True + + def __str__(self) -> str: + return f"" + + - async def save(self, chat_id, user_id, data): - self.data[chat_id][user_id]['data'] = data \ No newline at end of file diff --git a/telebot/asyncio_storage/pickle_storage.py b/telebot/asyncio_storage/pickle_storage.py index cf446d85b..fcffbb289 100644 --- a/telebot/asyncio_storage/pickle_storage.py +++ b/telebot/asyncio_storage/pickle_storage.py @@ -1,4 +1,4 @@ -from telebot.asyncio_storage.base_storage import StateStorageBase, StateContext +from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext import os import pickle @@ -103,7 +103,7 @@ async def set_data(self, chat_id, user_id, key, value): raise RuntimeError('chat_id {} and user_id {} does not exist'.format(chat_id, user_id)) def get_interactive_data(self, chat_id, user_id): - return StateContext(self, chat_id, user_id) + return StateDataContext(self, chat_id, user_id) async def save(self, chat_id, user_id, data): self.data[chat_id][user_id]['data'] = data diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index 84db253e5..86fde3716 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -1,4 +1,4 @@ -from telebot.asyncio_storage.base_storage import StateStorageBase, StateContext +from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext import json redis_installed = True @@ -167,7 +167,7 @@ def get_interactive_data(self, chat_id, user_id): Get Data in interactive way. You can use with() with this function. """ - return StateContext(self, chat_id, user_id) + return StateDataContext(self, chat_id, user_id) async def save(self, chat_id, user_id, data): response = await self.get_record(chat_id) diff --git a/telebot/states/__init__.py b/telebot/states/__init__.py index b8efe3bbe..015f135e4 100644 --- a/telebot/states/__init__.py +++ b/telebot/states/__init__.py @@ -16,7 +16,7 @@ def __init__(self) -> None: self.name: str = None self.group: StatesGroup = None def __str__(self) -> str: - return f"<{self.group.__name__}:{self.name}>" + return f"<{self.name}>" class StatesGroup: diff --git a/telebot/states/aio/__init__.py b/telebot/states/aio/__init__.py index e69de29bb..60f9ea2b7 100644 --- a/telebot/states/aio/__init__.py +++ b/telebot/states/aio/__init__.py @@ -0,0 +1,7 @@ +from .context import StateContext +from .middleware import StateMiddleware + +__all__ = [ + 'StateContext', + 'StateMiddleware', +] \ No newline at end of file diff --git a/telebot/states/aio/context.py b/telebot/states/aio/context.py new file mode 100644 index 000000000..431eba93c --- /dev/null +++ b/telebot/states/aio/context.py @@ -0,0 +1,138 @@ +from telebot.states import State, StatesGroup +from telebot.types import CallbackQuery, Message +from telebot.async_telebot import AsyncTeleBot +from telebot.states import resolve_context + +from typing import Union + + + +class StateContext(): + """ + Class representing a state context. + + Passed through a middleware to provide easy way to set states. + + .. code-block:: python3 + + @bot.message_handler(commands=['start']) + async def start_ex(message: types.Message, state_context: StateContext): + await state_context.set(MyStates.name) + await bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) + # also, state_context.data(), .add_data(), .reset_data(), .delete() methods available. + """ + + def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: + self.message: Union[Message, CallbackQuery] = message + self.bot: AsyncTeleBot = bot + self.bot_id = self.bot.bot_id + + async def set(self, state: Union[State, str]) -> None: + """ + Set state for current user. + + :param state: State object or state name. + :type state: Union[State, str] + + .. code-block:: python3 + + @bot.message_handler(commands=['start']) + async def start_ex(message: types.Message, state_context: StateContext): + await state_context.set(MyStates.name) + await bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + if isinstance(state, State): + state = state.name + return await self.bot.set_state( + chat_id=chat_id, + user_id=user_id, + state=state, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + async def get(self) -> str: + """ + Get current state for current user. + + :return: Current state name. + :rtype: str + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + return await self.bot.get_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + async def reset_data(self) -> None: + """ + Reset data for current user. + State will not be changed. + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + return await self.bot.reset_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + async def delete(self) -> None: + """ + Deletes state and data for current user. + """ + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + return await self.bot.delete_state( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + def data(self) -> dict: + """ + Get data for current user. + + .. code-block:: python3 + + with state_context.data() as data: + print(data) + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + return self.bot.retrieve_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id + ) + + async def add_data(self, **kwargs) -> None: + """ + Add data for current user. + + :param kwargs: Data to add. + :type kwargs: dict + """ + + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + return await self.bot.add_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + bot_id=bot_id, + message_thread_id=message_thread_id, + **kwargs + ) + \ No newline at end of file diff --git a/telebot/states/aio/middleware.py b/telebot/states/aio/middleware.py new file mode 100644 index 000000000..66283dc82 --- /dev/null +++ b/telebot/states/aio/middleware.py @@ -0,0 +1,19 @@ +from telebot.asyncio_handler_backends import BaseMiddleware +from telebot.async_telebot import AsyncTeleBot +from telebot.states.sync.context import StateContext +from telebot.util import update_types +from telebot import types + + +class StateMiddleware(BaseMiddleware): + + def __init__(self, bot: AsyncTeleBot) -> None: + self.update_sensitive = False + self.update_types = update_types + self.bot: AsyncTeleBot = bot + + async def pre_process(self, message, data): + data['state_context'] = StateContext(message, self.bot) + + async def post_process(self, message, data, exception): + pass diff --git a/telebot/storage/__init__.py b/telebot/storage/__init__.py index 59e2b058c..954c1b31d 100644 --- a/telebot/storage/__init__.py +++ b/telebot/storage/__init__.py @@ -1,13 +1,13 @@ from telebot.storage.memory_storage import StateMemoryStorage from telebot.storage.redis_storage import StateRedisStorage from telebot.storage.pickle_storage import StatePickleStorage -from telebot.storage.base_storage import StateContext,StateStorageBase +from telebot.storage.base_storage import StateDataContext,StateStorageBase __all__ = [ - 'StateStorageBase', 'StateContext', + 'StateStorageBase', 'StateDataContext', 'StateMemoryStorage', 'StateRedisStorage', 'StatePickleStorage' ] \ No newline at end of file diff --git a/telebot/storage/base_storage.py b/telebot/storage/base_storage.py index 2358e93c9..25a6c6b04 100644 --- a/telebot/storage/base_storage.py +++ b/telebot/storage/base_storage.py @@ -78,7 +78,7 @@ def _get_key( -class StateContext: +class StateDataContext: """ Class for data. """ diff --git a/telebot/storage/memory_storage.py b/telebot/storage/memory_storage.py index 547445d0c..82142430a 100644 --- a/telebot/storage/memory_storage.py +++ b/telebot/storage/memory_storage.py @@ -1,4 +1,4 @@ -from telebot.storage.base_storage import StateStorageBase, StateContext +from telebot.storage.base_storage import StateStorageBase, StateDataContext from typing import Optional, Union class StateMemoryStorage(StateStorageBase): @@ -105,7 +105,7 @@ def get_interactive_data( self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None ) -> Optional[dict]: - return StateContext( + return StateDataContext( self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id, bot_id=bot_id ) diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index 64ed7ce85..917491814 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -2,7 +2,7 @@ import pickle import threading from typing import Optional, Union -from telebot.storage.base_storage import StateStorageBase, StateContext +from telebot.storage.base_storage import StateStorageBase, StateDataContext class StatePickleStorage(StateStorageBase): def __init__(self, file_path: str="./.state-save/states.pkl", @@ -110,7 +110,7 @@ def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optiona def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Optional[dict]: - return StateContext( + return StateDataContext( self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id, bot_id=bot_id ) diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index b16ea3016..0aa7c43ea 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -1,5 +1,5 @@ import json -from telebot.storage.base_storage import StateStorageBase, StateContext +from telebot.storage.base_storage import StateStorageBase, StateDataContext from typing import Optional, Union redis_installed = True @@ -126,7 +126,7 @@ def get_interactive_data( self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, bot_id: Optional[int] = None ) -> Optional[dict]: - return StateContext( + return StateDataContext( self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id, bot_id=bot_id ) From ff6485d66570e497038f6a1cc9fa6ac10ee05f18 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 19 Jul 2024 21:26:33 +0500 Subject: [PATCH 304/480] Async version fully supported, partially tested. --- telebot/asyncio_storage/pickle_storage.py | 206 +++++++++------- telebot/asyncio_storage/redis_storage.py | 274 +++++++++------------- telebot/storage/pickle_storage.py | 5 +- telebot/storage/redis_storage.py | 4 +- 4 files changed, 237 insertions(+), 252 deletions(-) diff --git a/telebot/asyncio_storage/pickle_storage.py b/telebot/asyncio_storage/pickle_storage.py index fcffbb289..0c7da7eb1 100644 --- a/telebot/asyncio_storage/pickle_storage.py +++ b/telebot/asyncio_storage/pickle_storage.py @@ -1,28 +1,43 @@ -from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext -import os +try: + import aiofiles +except ImportError: + aiofiles_installed = False + +import os import pickle +import asyncio +from typing import Optional, Union, Callable, Any +from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext + +def with_lock(func: Callable) -> Callable: + async def wrapper(self, *args, **kwargs): + async with self.lock: + return await func(self, *args, **kwargs) + return wrapper class StatePickleStorage(StateStorageBase): - def __init__(self, file_path="./.state-save/states.pkl") -> None: + def __init__(self, file_path: str = "./.state-save/states.pkl", + prefix='telebot', separator: Optional[str] = ":") -> None: + + if not aiofiles_installed: + raise ImportError("Please install aiofiles using `pip install aiofiles`") + self.file_path = file_path + self.prefix = prefix + self.separator = separator + self.lock = asyncio.Lock() self.create_dir() - self.data = self.read() - - async def convert_old_to_new(self): - # old looks like: - # {1: {'state': 'start', 'data': {'name': 'John'}} - # we should update old version pickle to new. - # new looks like: - # {1: {2: {'state': 'start', 'data': {'name': 'John'}}}} - new_data = {} - for key, value in self.data.items(): - # this returns us id and dict with data and state - new_data[key] = {key: value} # convert this to new - # pass it to global data - self.data = new_data - self.update_data() # update data in file + + async def _read_from_file(self) -> dict: + async with aiofiles.open(self.file_path, 'rb') as f: + data = await f.read() + return pickle.loads(data) + + async def _write_to_file(self, data: dict) -> None: + async with aiofiles.open(self.file_path, 'wb') as f: + await f.write(pickle.dumps(data)) def create_dir(self): """ @@ -34,77 +49,100 @@ def create_dir(self): with open(self.file_path,'wb') as file: pickle.dump({}, file) - def read(self): - file = open(self.file_path, 'rb') - data = pickle.load(file) - file.close() - return data - - def update_data(self): - file = open(self.file_path, 'wb+') - pickle.dump(self.data, file, protocol=pickle.HIGHEST_PROTOCOL) - file.close() - - async def set_state(self, chat_id, user_id, state): - if hasattr(state, 'name'): - state = state.name - if chat_id in self.data: - if user_id in self.data[chat_id]: - self.data[chat_id][user_id]['state'] = state - self.update_data() - return True - else: - self.data[chat_id][user_id] = {'state': state, 'data': {}} - self.update_data() - return True - self.data[chat_id] = {user_id: {'state': state, 'data': {}}} - self.update_data() + + @with_lock + async def set_state(self, chat_id: int, user_id: int, state: str, + business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + if _key not in data: + data[_key] = {"state": state, "data": {}} + else: + data[_key]["state"] = state + await self._write_to_file(data) return True - - async def delete_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - del self.data[chat_id][user_id] - if chat_id == user_id: - del self.data[chat_id] - self.update_data() - return True + @with_lock + async def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Union[str, None]: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + return data.get(_key, {}).get("state") + + @with_lock + async def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + if _key in data: + del data[_key] + await self._write_to_file(data) + return True return False - - async def get_state(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['state'] - - return None - async def get_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - return self.data[chat_id][user_id]['data'] - - return None - - async def reset_data(self, chat_id, user_id): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'] = {} - self.update_data() - return True + @with_lock + async def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + state_data = data.get(_key, {}) + state_data["data"][key] = value + if _key not in data: + data[_key] = {"state": None, "data": state_data} + else: + data[_key]["data"][key] = value + await self._write_to_file(data) + return True + + @with_lock + async def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> dict: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + return data.get(_key, {}).get("data", {}) + + @with_lock + async def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + if _key in data: + data[_key]["data"] = {} + await self._write_to_file(data) + return True return False - async def set_data(self, chat_id, user_id, key, value): - if self.data.get(chat_id): - if self.data[chat_id].get(user_id): - self.data[chat_id][user_id]['data'][key] = value - self.update_data() - return True - raise RuntimeError('chat_id {} and user_id {} does not exist'.format(chat_id, user_id)) + def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Optional[dict]: + return StateDataContext( + self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id + ) - def get_interactive_data(self, chat_id, user_id): - return StateDataContext(self, chat_id, user_id) + @with_lock + async def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + _key = self._get_key( + chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + ) + data = await self._read_from_file() + data[_key]["data"] = data + await self._write_to_file(data) + return True - async def save(self, chat_id, user_id, data): - self.data[chat_id][user_id]['data'] = data - self.update_data() \ No newline at end of file + def __str__(self) -> str: + return f"StatePickleStorage({self.file_path}, {self.prefix})" diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index 86fde3716..a6b19780d 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -1,179 +1,131 @@ -from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext -import json -redis_installed = True -is_actual_aioredis = False try: - import aioredis - is_actual_aioredis = True + import redis + from redis.asyncio import Redis, ConnectionPool except ImportError: - try: - from redis import asyncio as aioredis - except ImportError: - redis_installed = False + redis_installed = False + +import json +from typing import Optional, Union, Callable, Coroutine +import asyncio + +from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext + + +def async_with_lock(func: Callable[..., Coroutine]) -> Callable[..., Coroutine]: + async def wrapper(self, *args, **kwargs): + async with self.lock: + return await func(self, *args, **kwargs) + return wrapper +def async_with_pipeline(func: Callable[..., Coroutine]) -> Callable[..., Coroutine]: + async def wrapper(self, *args, **kwargs): + async with self.redis.pipeline() as pipe: + pipe.multi() + result = await func(self, pipe, *args, **kwargs) + await pipe.execute() + return result + return wrapper class StateRedisStorage(StateStorageBase): - """ - This class is for Redis storage. - This will work only for states. - To use it, just pass this class to: - TeleBot(storage=StateRedisStorage()) - """ - def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_', redis_url=None): + def __init__(self, host='localhost', port=6379, db=0, password=None, + prefix='telebot', + redis_url=None, + connection_pool: 'ConnectionPool'=None, + separator: Optional[str] = ":", + ) -> None: + if not redis_installed: - raise ImportError('AioRedis is not installed. Install it via "pip install aioredis"') + raise ImportError("Please install redis using `pip install redis`") + + self.separator = separator + self.prefix = prefix + if not self.prefix: + raise ValueError("Prefix cannot be empty") - if is_actual_aioredis: - aioredis_version = tuple(map(int, aioredis.__version__.split(".")[0])) - if aioredis_version < (2,): - raise ImportError('Invalid aioredis version. Aioredis version should be >= 2.0.0') if redis_url: - self.redis = aioredis.Redis.from_url(redis_url) + self.redis = redis.asyncio.from_url(redis_url) + elif connection_pool: + self.redis = Redis(connection_pool=connection_pool) else: - self.redis = aioredis.Redis(host=host, port=port, db=db, password=password) + self.redis = Redis(host=host, port=port, db=db, password=password) + + self.lock = asyncio.Lock() + + @async_with_lock + @async_with_pipeline + async def set_state(self, pipe, chat_id: int, user_id: int, state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + if hasattr(state, "name"): + state = state.name - self.prefix = prefix - #self.con = Redis(connection_pool=self.redis) -> use this when necessary - # - # {chat_id: {user_id: {'state': None, 'data': {}}, ...}, ...} - - async def get_record(self, key): - """ - Function to get record from database. - It has nothing to do with states. - Made for backward compatibility - """ - result = await self.redis.get(self.prefix+str(key)) - if result: return json.loads(result) - return - - async def set_record(self, key, value): - """ - Function to set record to database. - It has nothing to do with states. - Made for backward compatibility - """ - - await self.redis.set(self.prefix+str(key), json.dumps(value)) + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + await pipe.hset(_key, "state", state) return True - async def delete_record(self, key): - """ - Function to delete record from database. - It has nothing to do with states. - Made for backward compatibility - """ - await self.redis.delete(self.prefix+str(key)) + async def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Union[str, None]: + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + state_bytes = await self.redis.hget(_key, "state") + return state_bytes.decode('utf-8') if state_bytes else None + + async def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + result = await self.redis.delete(_key) + return result > 0 + + @async_with_lock + @async_with_pipeline + async def set_data(self, pipe, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None) -> bool: + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + data = await pipe.hget(_key, "data") + data = await pipe.execute() + data = data[0] + if data is None: + await pipe.hset(_key, "data", json.dumps({key: value})) + else: + data = json.loads(data) + data[key] = value + await pipe.hset(_key, "data", json.dumps(data)) return True - async def set_state(self, chat_id, user_id, state): - """ - Set state for a particular user in a chat. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if hasattr(state, 'name'): - state = state.name - if response: - if user_id in response: - response[user_id]['state'] = state - else: - response[user_id] = {'state': state, 'data': {}} + async def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> dict: + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + data = await self.redis.hget(_key, "data") + return json.loads(data) if data else {} + + @async_with_lock + @async_with_pipeline + async def reset_data(self, pipe, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + if await pipe.exists(_key): + await pipe.hset(_key, "data", "{}") else: - response = {user_id: {'state': state, 'data': {}}} - await self.set_record(chat_id, response) + return False + return True + def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Optional[dict]: + return StateDataContext(self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, + message_thread_id=message_thread_id, bot_id=bot_id) + + @async_with_lock + @async_with_pipeline + async def save(self, pipe, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + if await pipe.exists(_key): + await pipe.hset(_key, "data", json.dumps(data)) + else: + return False return True - - async def delete_state(self, chat_id, user_id): - """ - Delete state for a particular user in a chat. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - del response[user_id] - if user_id == str(chat_id): - await self.delete_record(chat_id) - return True - else: await self.set_record(chat_id, response) - return True - return False - - async def get_value(self, chat_id, user_id, key): - """ - Get value for a data of a user in a chat. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - if key in response[user_id]['data']: - return response[user_id]['data'][key] - return None - - async def get_state(self, chat_id, user_id): - """ - Get state of a user in a chat. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - return response[user_id]['state'] - - return None - - async def get_data(self, chat_id, user_id): - """ - Get data of particular user in a particular chat. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - return response[user_id]['data'] - return None - - async def reset_data(self, chat_id, user_id): - """ - Reset data of a user in a chat. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - response[user_id]['data'] = {} - await self.set_record(chat_id, response) - return True - - async def set_data(self, chat_id, user_id, key, value): - """ - Set data without interactive data. - """ - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - response[user_id]['data'][key] = value - await self.set_record(chat_id, response) - return True - return False - - def get_interactive_data(self, chat_id, user_id): - """ - Get Data in interactive way. - You can use with() with this function. - """ - return StateDataContext(self, chat_id, user_id) - - async def save(self, chat_id, user_id, data): - response = await self.get_record(chat_id) - user_id = str(user_id) - if response: - if user_id in response: - response[user_id]['data'] = data - await self.set_record(chat_id, response) - return True + + def __str__(self) -> str: + # include some connection info + return f"StateRedisStorage({self.redis})" diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index 917491814..32a9653c7 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -127,7 +127,4 @@ def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: O return True def __str__(self) -> str: - with self.lock: - with open(self.file_path, 'rb') as f: - data = pickle.load(f) - return f"" + return f"StatePickleStorage({self.file_path}, {self.prefix})" diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 0aa7c43ea..d41da05c8 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -151,6 +151,4 @@ def save_action(pipe): return True def __str__(self) -> str: - keys = self.redis.keys(f"{self.prefix}{self.separator}*") - data = {key.decode(): self.redis.hgetall(key) for key in keys} - return f"" + return f"StateRedisStorage({self.redis})" From 1a47edf9db5e25b91bbc52c77ada19e32236ec12 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 21 Jul 2024 18:27:45 +0500 Subject: [PATCH 305/480] Fix #2339 --- telebot/asyncio_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index da794b77b..f4e594a7a 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -301,7 +301,7 @@ async def check(self, message): """ :meta private: """ - return message.forward_date is not None + return message.forward_origin is not None class IsReplyFilter(SimpleCustomFilter): From af79db6ad3528d01be167bec02cc6799dfe67526 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 21 Jul 2024 20:15:57 +0500 Subject: [PATCH 306/480] rewrote pickle sync with lock decorators, few changes to storages to return empty dict on get_data & raise runtimeerror on key not existing --- telebot/asyncio_storage/memory_storage.py | 4 +- telebot/asyncio_storage/pickle_storage.py | 2 +- telebot/asyncio_storage/redis_storage.py | 2 +- telebot/storage/memory_storage.py | 4 +- telebot/storage/pickle_storage.py | 124 ++++++++++++---------- telebot/storage/redis_storage.py | 2 +- 6 files changed, 72 insertions(+), 66 deletions(-) diff --git a/telebot/asyncio_storage/memory_storage.py b/telebot/asyncio_storage/memory_storage.py index e65ed74d4..661cc35e9 100644 --- a/telebot/asyncio_storage/memory_storage.py +++ b/telebot/asyncio_storage/memory_storage.py @@ -71,7 +71,7 @@ async def set_data( ) if self.data.get(_key) is None: - return False + raise RuntimeError(f"MemoryStorage: key {_key} does not exist.") self.data[_key]["data"][key] = value return True @@ -85,7 +85,7 @@ async def get_data( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - return self.data.get(_key, {}).get("data", None) + return self.data.get(_key, {}).get("data", {}) async def reset_data( self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, diff --git a/telebot/asyncio_storage/pickle_storage.py b/telebot/asyncio_storage/pickle_storage.py index 0c7da7eb1..9a8c9eead 100644 --- a/telebot/asyncio_storage/pickle_storage.py +++ b/telebot/asyncio_storage/pickle_storage.py @@ -98,7 +98,7 @@ async def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, state_data = data.get(_key, {}) state_data["data"][key] = value if _key not in data: - data[_key] = {"state": None, "data": state_data} + raise RuntimeError(f"StatePickleStorage: key {_key} does not exist.") else: data[_key]["data"][key] = value await self._write_to_file(data) diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index a6b19780d..b07bd4159 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -86,7 +86,7 @@ async def set_data(self, pipe, chat_id: int, user_id: int, key: str, value: Unio data = await pipe.execute() data = data[0] if data is None: - await pipe.hset(_key, "data", json.dumps({key: value})) + raise RuntimeError(f"StateRedisStorage: key {_key} does not exist.") else: data = json.loads(data) data[key] = value diff --git a/telebot/storage/memory_storage.py b/telebot/storage/memory_storage.py index 82142430a..11acdc119 100644 --- a/telebot/storage/memory_storage.py +++ b/telebot/storage/memory_storage.py @@ -71,7 +71,7 @@ def set_data( ) if self.data.get(_key) is None: - return False + raise RuntimeError(f"StateMemoryStorage: key {_key} does not exist.") self.data[_key]["data"][key] = value return True @@ -85,7 +85,7 @@ def get_data( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - return self.data.get(_key, {}).get("data", None) + return self.data.get(_key, {}).get("data", {}) def reset_data( self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index 32a9653c7..b449c17f4 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -1,12 +1,18 @@ import os import pickle import threading -from typing import Optional, Union +from typing import Optional, Union, Callable from telebot.storage.base_storage import StateStorageBase, StateDataContext +def with_lock(func: Callable) -> Callable: + def wrapper(self, *args, **kwargs): + with self.lock: + return func(self, *args, **kwargs) + return wrapper + class StatePickleStorage(StateStorageBase): - def __init__(self, file_path: str="./.state-save/states.pkl", - prefix='telebot', separator: Optional[str]=":") -> None: + def __init__(self, file_path: str = "./.state-save/states.pkl", + prefix='telebot', separator: Optional[str] = ":") -> None: self.file_path = file_path self.prefix = prefix self.separator = separator @@ -32,98 +38,98 @@ def create_dir(self): with open(self.file_path,'wb') as file: pickle.dump({}, file) + @with_lock def set_state(self, chat_id: int, user_id: int, state: str, - business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, - bot_id: Optional[int]=None) -> bool: + business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None) -> bool: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - if _key not in data: - data[_key] = {"state": state, "data": {}} - else: - data[_key]["state"] = state - self._write_to_file(data) + data = self._read_from_file() + if _key not in data: + data[_key] = {"state": state, "data": {}} + else: + data[_key]["state"] = state + self._write_to_file(data) return True - def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Union[str, None]: + @with_lock + def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Union[str, None]: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - return data.get(_key, {}).get("state") + data = self._read_from_file() + return data.get(_key, {}).get("state") - def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: + @with_lock + def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - if _key in data: - del data[_key] - self._write_to_file(data) - return True - return False + data = self._read_from_file() + if _key in data: + del data[_key] + self._write_to_file(data) + return True + return False + @with_lock def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, - bot_id: Optional[int]=None) -> bool: + business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None) -> bool: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - state_data = data.get(_key, {}) - state_data["data"][key] = value - if _key not in data: - data[_key] = {"state": None, "data": state_data} - else: - data[_key]["data"][key] = value - self._write_to_file(data) + data = self._read_from_file() + state_data = data.get(_key, {}) + state_data["data"][key] = value + + if _key not in data: + raise RuntimeError(f"PickleStorage: key {_key} does not exist.") + + self._write_to_file(data) return True - def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> dict: + @with_lock + def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> dict: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - return data.get(_key, {}).get("data", {}) + data = self._read_from_file() + return data.get(_key, {}).get("data", {}) - def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: + @with_lock + def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - if _key in data: - data[_key]["data"] = {} - self._write_to_file(data) - return True - return False + data = self._read_from_file() + if _key in data: + data[_key]["data"] = {} + self._write_to_file(data) + return True + return False - def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Optional[dict]: + def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Optional[dict]: return StateDataContext( self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id, bot_id=bot_id ) - def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: + @with_lock + def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: _key = self._get_key( chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id ) - with self.lock: - data = self._read_from_file() - data[_key]["data"] = data - self._write_to_file(data) + data = self._read_from_file() + data[_key]["data"] = data + self._write_to_file(data) return True def __str__(self) -> str: diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index d41da05c8..f21d50fe1 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -85,7 +85,7 @@ def set_data_action(pipe): data = pipe.hget(_key, "data") data = data.execute()[0] if data is None: - pipe.hset(_key, "data", json.dumps({key: value})) + raise RuntimeError(f"RedisStorage: key {_key} does not exist.") else: data = json.loads(data) data[key] = value From 1adca1375b6901b0963fd020f697825032b551d5 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 21 Jul 2024 22:27:08 +0500 Subject: [PATCH 307/480] Improved docstrings, fixed bugs, allow accessing statecontext via state name --- telebot/__init__.py | 52 ++++++++++++++++------- telebot/async_telebot.py | 43 +++++++++++++------ telebot/asyncio_storage/memory_storage.py | 17 ++++++++ telebot/asyncio_storage/pickle_storage.py | 24 +++++++++++ telebot/asyncio_storage/redis_storage.py | 34 +++++++++++++++ telebot/states/aio/context.py | 23 ++++++---- telebot/states/aio/middleware.py | 4 +- telebot/states/sync/context.py | 25 ++++++----- telebot/states/sync/middleware.py | 4 +- telebot/storage/memory_storage.py | 16 +++++++ telebot/storage/pickle_storage.py | 24 +++++++++++ telebot/storage/redis_storage.py | 33 ++++++++++++++ 12 files changed, 248 insertions(+), 51 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 08ae9fc6f..07ae33181 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6645,9 +6645,9 @@ def setup_middleware(self, middleware: BaseMiddleware): self.middlewares.append(middleware) - def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None, + def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, - bot_id: Optional[int]=None) -> None: + bot_id: Optional[int]=None) -> bool: """ Sets a new state of a user. @@ -6657,16 +6657,24 @@ def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Option Otherwise, if you only set user_id, chat_id will equal to user_id, this means that state will be set for the user in his private chat with a bot. + .. versionchanged:: 4.22.0 + + Added additional parameters to support topics, business connections, and message threads. + + .. seealso:: + + For more details, visit the `custom_states.py example `_. + :param user_id: User's identifier :type user_id: :obj:`int` - :param state: new state. can be string, integer, or :class:`telebot.types.State` + :param state: new state. can be string, or :class:`telebot.types.State` :type state: :obj:`int` or :obj:`str` or :class:`telebot.types.State` :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier @@ -6675,7 +6683,8 @@ def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Option :param message_thread_id: Identifier of the message thread :type message_thread_id: :obj:`int` - :return: None + :return: True on success + :rtype: :obj:`bool` """ if chat_id is None: chat_id = user_id @@ -6688,9 +6697,9 @@ def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Option def reset_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ - Reset data for a user in chat. + Reset data for a user in chat: sets the 'data' fieldi to an empty dictionary. :param user_id: User's identifier :type user_id: :obj:`int` @@ -6698,7 +6707,7 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None, :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier @@ -6707,7 +6716,8 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None, :param message_thread_id: Identifier of the message thread :type message_thread_id: :obj:`int` - :return: None + :return: True on success + :rtype: :obj:`bool` """ if chat_id is None: chat_id = user_id @@ -6718,9 +6728,13 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None, def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ - Delete the current state of a user. + Fully deletes the storage record of a user in chat. + + .. warning:: + + This does NOT set state to None, but deletes the object from storage. :param user_id: User's identifier :type user_id: :obj:`int` @@ -6728,7 +6742,8 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_conne :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :return: None + :return: True on success + :rtype: :obj:`bool` """ if chat_id is None: chat_id = user_id @@ -6749,7 +6764,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn :param chat_id: Chat's unique identifier, defaults to user_id :type chat_id: int, optional - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: int, optional :param business_connection_id: Business identifier @@ -6772,18 +6787,23 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn def get_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Union[int, str]: + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> str: """ Gets current state of a user. Not recommended to use this method. But it is ok for debugging. + .. warning:: + + Even if you are using :class:`telebot.types.State`, this method will return a string. + When comparing(not recommended), you should compare this string with :class:`telebot.types.State`.name + :param user_id: User's identifier :type user_id: :obj:`int` :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier @@ -6817,7 +6837,7 @@ def add_data(self, user_id: int, chat_id: Optional[int]=None, :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 2d443cb5b..508aa6cb4 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7846,7 +7846,7 @@ async def get_forum_topic_icon_stickers(self) -> List[types.Sticker]: async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, - bot_id: Optional[int]=None) -> None: + bot_id: Optional[int]=None) -> bool: """ Sets a new state of a user. @@ -7856,16 +7856,24 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Otherwise, if you only set user_id, chat_id will equal to user_id, this means that state will be set for the user in his private chat with a bot. + .. versionchanged:: 4.22.0 + + Added additional parameters to support topics, business connections, and message threads. + + .. seealso:: + + For more details, visit the `custom_states.py example `_. + :param user_id: User's identifier :type user_id: :obj:`int` - :param state: new state. can be string, integer, or :class:`telebot.types.State` + :param state: new state. can be string, or :class:`telebot.types.State` :type state: :obj:`int` or :obj:`str` or :class:`telebot.types.State` :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier @@ -7874,7 +7882,8 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: :param message_thread_id: Identifier of the message thread :type message_thread_id: :obj:`int` - :return: None + :return: True on success + :rtype: :obj:`bool` """ if chat_id is None: chat_id = user_id @@ -7887,7 +7896,7 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: async def reset_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ Reset data for a user in chat. @@ -7897,7 +7906,7 @@ async def reset_data(self, user_id: int, chat_id: Optional[int]=None, :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier @@ -7906,7 +7915,8 @@ async def reset_data(self, user_id: int, chat_id: Optional[int]=None, :param message_thread_id: Identifier of the message thread :type message_thread_id: :obj:`int` - :return: None + :return: True on success + :rtype: :obj:`bool` """ if chat_id is None: chat_id = user_id @@ -7917,7 +7927,7 @@ async def reset_data(self, user_id: int, chat_id: Optional[int]=None, async def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> None: + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ Delete the current state of a user. @@ -7948,7 +7958,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn :param chat_id: Chat's unique identifier, defaults to user_id :type chat_id: int, optional - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: int, optional :param business_connection_id: Business identifier @@ -7958,7 +7968,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn :type message_thread_id: int, optional :return: Context manager with data for a user in chat - :rtype: Optional[Any] + :rtype: :obj:`dict` """ if chat_id is None: chat_id = user_id @@ -7971,18 +7981,23 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn async def get_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> Union[int, str]: + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> str: """ Gets current state of a user. Not recommended to use this method. But it is ok for debugging. + .. warning:: + + Even if you are using :class:`telebot.types.State`, this method will return a string. + When comparing(not recommended), you should compare this string with :class:`telebot.types.State`.name + :param user_id: User's identifier :type user_id: :obj:`int` :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier @@ -7992,7 +8007,7 @@ async def get_state(self, user_id: int, chat_id: Optional[int]=None, :type message_thread_id: :obj:`int` :return: state of a user - :rtype: :obj:`int` or :obj:`str` or :class:`telebot.types.State` + :rtype: :obj:`str` """ if chat_id is None: chat_id = user_id @@ -8016,7 +8031,7 @@ async def add_data(self, user_id: int, chat_id: Optional[int]=None, :param chat_id: Chat's identifier :type chat_id: :obj:`int` - :param bot_id: Bot's identifier + :param bot_id: Bot's identifier, defaults to current bot id :type bot_id: :obj:`int` :param business_connection_id: Business identifier diff --git a/telebot/asyncio_storage/memory_storage.py b/telebot/asyncio_storage/memory_storage.py index 661cc35e9..87449cace 100644 --- a/telebot/asyncio_storage/memory_storage.py +++ b/telebot/asyncio_storage/memory_storage.py @@ -2,6 +2,23 @@ from typing import Optional, Union class StateMemoryStorage(StateStorageBase): + """ + Memory storage for states. + + Stores states in memory as a dictionary. + + .. code-block:: python3 + + storage = StateMemoryStorage() + bot = AsyncTeleBot(token, storage=storage) + + :param separator: Separator for keys, default is ":". + :type separator: Optional[str] + + :param prefix: Prefix for keys, default is "telebot". + :type prefix: Optional[str] + """ + def __init__(self, separator: Optional[str]=":", prefix: Optional[str]="telebot" diff --git a/telebot/asyncio_storage/pickle_storage.py b/telebot/asyncio_storage/pickle_storage.py index 9a8c9eead..0506d4703 100644 --- a/telebot/asyncio_storage/pickle_storage.py +++ b/telebot/asyncio_storage/pickle_storage.py @@ -1,4 +1,5 @@ +aiofiles_installed = True try: import aiofiles except ImportError: @@ -18,6 +19,29 @@ async def wrapper(self, *args, **kwargs): return wrapper class StatePickleStorage(StateStorageBase): + """ + State storage based on pickle file. + + .. warning:: + + This storage is not recommended for production use. + Data may be corrupted. If you face a case where states do not work as expected, + try to use another storage. + + .. code-block:: python3 + + storage = StatePickleStorage() + bot = AsyncTeleBot(token, storage=storage) + + :param file_path: Path to file where states will be stored. + :type file_path: str + + :param prefix: Prefix for keys, default is "telebot". + :type prefix: Optional[str] + + :param separator: Separator for keys, default is ":". + :type separator: Optional[str] + """ def __init__(self, file_path: str = "./.state-save/states.pkl", prefix='telebot', separator: Optional[str] = ":") -> None: diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index b07bd4159..dea214daa 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -1,4 +1,5 @@ +redis_installed = True try: import redis from redis.asyncio import Redis, ConnectionPool @@ -28,6 +29,39 @@ async def wrapper(self, *args, **kwargs): return wrapper class StateRedisStorage(StateStorageBase): + """ + State storage based on Redis. + + .. code-block:: python3 + + storage = StateRedisStorage(...) + bot = AsyncTeleBot(token, storage=storage) + + :param host: Redis host, default is "localhost". + :type host: str + + :param port: Redis port, default is 6379. + :type port: int + + :param db: Redis database, default is 0. + :type db: int + + :param password: Redis password, default is None. + :type password: Optional[str] + + :param prefix: Prefix for keys, default is "telebot". + :type prefix: Optional[str] + + :param redis_url: Redis URL, default is None. + :type redis_url: Optional[str] + + :param connection_pool: Redis connection pool, default is None. + :type connection_pool: Optional[ConnectionPool] + + :param separator: Separator for keys, default is ":". + :type separator: Optional[str] + + """ def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot', redis_url=None, diff --git a/telebot/states/aio/context.py b/telebot/states/aio/context.py index 431eba93c..956ca6837 100644 --- a/telebot/states/aio/context.py +++ b/telebot/states/aio/context.py @@ -27,7 +27,7 @@ def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: self.bot: AsyncTeleBot = bot self.bot_id = self.bot.bot_id - async def set(self, state: Union[State, str]) -> None: + async def set(self, state: Union[State, str]) -> bool: """ Set state for current user. @@ -71,14 +71,16 @@ async def get(self) -> str: message_thread_id=message_thread_id ) - async def reset_data(self) -> None: - """ - Reset data for current user. - State will not be changed. + async def delete(self) -> bool: """ + Deletes state and data for current user. + .. warning:: + + This method deletes state and associated data for current user. + """ chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) - return await self.bot.reset_data( + return await self.bot.delete_state( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, @@ -86,12 +88,14 @@ async def reset_data(self) -> None: message_thread_id=message_thread_id ) - async def delete(self) -> None: + async def reset_data(self) -> bool: """ - Deletes state and data for current user. + Reset data for current user. + State will not be changed. """ + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) - return await self.bot.delete_state( + return await self.bot.reset_data( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, @@ -107,6 +111,7 @@ def data(self) -> dict: with state_context.data() as data: print(data) + data['name'] = 'John' """ chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) diff --git a/telebot/states/aio/middleware.py b/telebot/states/aio/middleware.py index 66283dc82..546b29067 100644 --- a/telebot/states/aio/middleware.py +++ b/telebot/states/aio/middleware.py @@ -13,7 +13,9 @@ def __init__(self, bot: AsyncTeleBot) -> None: self.bot: AsyncTeleBot = bot async def pre_process(self, message, data): - data['state_context'] = StateContext(message, self.bot) + state_context = StateContext(message, self.bot) + data['state_context'] = state_context + data['state'] = state_context # 2 ways to access state context async def post_process(self, message, data, exception): pass diff --git a/telebot/states/sync/context.py b/telebot/states/sync/context.py index c8009007a..c0611f6bb 100644 --- a/telebot/states/sync/context.py +++ b/telebot/states/sync/context.py @@ -27,7 +27,7 @@ def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: self.bot: TeleBot = bot self.bot_id = self.bot.bot_id - def set(self, state: Union[State, str]) -> None: + def set(self, state: Union[State, str]) -> bool: """ Set state for current user. @@ -71,27 +71,31 @@ def get(self) -> str: message_thread_id=message_thread_id ) - def reset_data(self) -> None: - """ - Reset data for current user. - State will not be changed. + def delete(self) -> bool: """ + Deletes state and data for current user. + .. warning:: + + This method deletes state and associated data for current user. + """ chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) - return self.bot.reset_data( + return self.bot.delete_state( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, bot_id=bot_id, message_thread_id=message_thread_id ) - - def delete(self) -> None: + + def reset_data(self) -> bool: """ - Deletes state and data for current user. + Reset data for current user. + State will not be changed. """ + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) - return self.bot.delete_state( + return self.bot.reset_data( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, @@ -107,6 +111,7 @@ def data(self) -> dict: with state_context.data() as data: print(data) + data['name'] = 'John' """ chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) diff --git a/telebot/states/sync/middleware.py b/telebot/states/sync/middleware.py index b85f795da..4a252158b 100644 --- a/telebot/states/sync/middleware.py +++ b/telebot/states/sync/middleware.py @@ -13,7 +13,9 @@ def __init__(self, bot: TeleBot) -> None: self.bot: TeleBot = bot def pre_process(self, message, data): - data['state_context'] = StateContext(message, self.bot) + state_context = StateContext(message, self.bot) + data['state_context'] = state_context + data['state'] = state_context # 2 ways to access state context def post_process(self, message, data, exception): pass diff --git a/telebot/storage/memory_storage.py b/telebot/storage/memory_storage.py index 11acdc119..dc88bcebc 100644 --- a/telebot/storage/memory_storage.py +++ b/telebot/storage/memory_storage.py @@ -2,6 +2,22 @@ from typing import Optional, Union class StateMemoryStorage(StateStorageBase): + """ + Memory storage for states. + + Stores states in memory as a dictionary. + + .. code-block:: python3 + + storage = StateMemoryStorage() + bot = TeleBot(token, storage=storage) + + :param separator: Separator for keys, default is ":". + :type separator: Optional[str] + + :param prefix: Prefix for keys, default is "telebot". + :type prefix: Optional[str] + """ def __init__(self, separator: Optional[str]=":", prefix: Optional[str]="telebot" diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index b449c17f4..fc8dc3289 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -11,6 +11,30 @@ def wrapper(self, *args, **kwargs): return wrapper class StatePickleStorage(StateStorageBase): + """ + State storage based on pickle file. + + .. warning:: + + This storage is not recommended for production use. + Data may be corrupted. If you face a case where states do not work as expected, + try to use another storage. + + .. code-block:: python3 + + storage = StatePickleStorage() + bot = TeleBot(token, storage=storage) + + :param file_path: Path to file where states will be stored. + :type file_path: str + + :param prefix: Prefix for keys, default is "telebot". + :type prefix: Optional[str] + + :param separator: Separator for keys, default is ":". + :type separator: Optional[str] + """ + def __init__(self, file_path: str = "./.state-save/states.pkl", prefix='telebot', separator: Optional[str] = ":") -> None: self.file_path = file_path diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index f21d50fe1..146ec2f63 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -9,6 +9,39 @@ redis_installed = False class StateRedisStorage(StateStorageBase): + """ + State storage based on Redis. + + .. code-block:: python3 + + storage = StateRedisStorage(...) + bot = TeleBot(token, storage=storage) + + :param host: Redis host, default is "localhost". + :type host: str + + :param port: Redis port, default is 6379. + :type port: int + + :param db: Redis database, default is 0. + :type db: int + + :param password: Redis password, default is None. + :type password: Optional[str] + + :param prefix: Prefix for keys, default is "telebot". + :type prefix: Optional[str] + + :param redis_url: Redis URL, default is None. + :type redis_url: Optional[str] + + :param connection_pool: Redis connection pool, default is None. + :type connection_pool: Optional[ConnectionPool] + + :param separator: Separator for keys, default is ":". + :type separator: Optional[str] + + """ def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot', redis_url=None, From adae7a9ba4b137a3ed46db48a8a52cf0b089b692 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 21 Jul 2024 22:33:08 +0500 Subject: [PATCH 308/480] Removed aioredis from optional dependencies, breaking change made for states="*" --- pyproject.toml | 1 - telebot/asyncio_filters.py | 6 +++++- telebot/custom_filters.py | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0095c3f21..d5289361b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,6 @@ Issues = "https://github.com/eternnoir/pyTelegramBotAPI/issues" json = ["ujson"] PIL = ["Pillow"] redis = ["redis>=3.4.1"] -aioredis = ["aioredis"] aiohttp = ["aiohttp"] fastapi = ["fastapi"] uvicorn = ["uvicorn"] diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index 389ce1643..f8212f934 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -397,7 +397,6 @@ async def check(self, message, text): """ :meta private: """ - if text == '*': return True chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) @@ -421,10 +420,15 @@ async def check(self, message, text): message_thread_id=message_thread_id ) + # CHANGED BEHAVIOUR + if text == "*" and user_state is not None: + return True + if user_state == text: return True elif type(text) is list and user_state in text: return True + return False class IsDigitFilter(SimpleCustomFilter): diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index e53c669a1..2e91e55ea 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -403,7 +403,6 @@ def check(self, message, text): """ :meta private: """ - if text == '*': return True chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) @@ -427,10 +426,15 @@ def check(self, message, text): message_thread_id=message_thread_id ) + # CHANGED BEHAVIOUR + if text == "*" and user_state is not None: + return True + if user_state == text: return True elif type(text) is list and user_state in text: return True + return False class IsDigitFilter(SimpleCustomFilter): """ From d33db8532f1505d240dc53c79c9eeb5995a7fb95 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 21 Jul 2024 22:55:57 +0500 Subject: [PATCH 309/480] Updated examples --- .../asynchronous_telebot/custom_states.py | 169 +++++++++------- examples/custom_states.py | 186 +++++++++--------- 2 files changed, 191 insertions(+), 164 deletions(-) diff --git a/examples/asynchronous_telebot/custom_states.py b/examples/asynchronous_telebot/custom_states.py index aefad9809..eefc6ebbb 100644 --- a/examples/asynchronous_telebot/custom_states.py +++ b/examples/asynchronous_telebot/custom_states.py @@ -1,91 +1,112 @@ -from telebot import asyncio_filters -from telebot.async_telebot import AsyncTeleBot - -# list of storages, you can use any storage +from telebot import async_telebot +from telebot import asyncio_filters, types +from telebot.states import State, StatesGroup +from telebot.states.aio.context import StateContext from telebot.asyncio_storage import StateMemoryStorage -# new feature for states. -from telebot.asyncio_handler_backends import State, StatesGroup - -# default state storage is statememorystorage -bot = AsyncTeleBot('TOKEN', state_storage=StateMemoryStorage()) - +# Initialize the bot +state_storage = StateMemoryStorage() # don't use this in production; switch to redis +bot = async_telebot.AsyncTeleBot("TOKEN", state_storage=state_storage) -# Just create different statesgroup +# Define states class MyStates(StatesGroup): - name = State() # statesgroup should contain states - surname = State() + name = State() age = State() + color = State() + hobby = State() - - -# set_state -> sets a new state -# delete_state -> delets state if exists -# get_state -> returns state if exists - - +# Start command handler @bot.message_handler(commands=['start']) -async def start_ex(message): - """ - Start command. Here we are starting state - """ - await bot.set_state(message.from_user.id, MyStates.name, message.chat.id) - await bot.send_message(message.chat.id, 'Hi, write me a name') - - - -@bot.message_handler(state="*", commands='cancel') -async def any_state(message): - """ - Cancel state - """ - await bot.send_message(message.chat.id, "Your state was cancelled.") - await bot.delete_state(message.from_user.id, message.chat.id) +async def start_ex(message: types.Message, state: StateContext): + await state.set(MyStates.name) + await bot.send_message(message.chat.id, 'Hello! What is your first name?', reply_to_message_id=message.message_id) + +# Cancel command handler +@bot.message_handler(state="*", commands=['cancel']) +async def any_state(message: types.Message, state: StateContext): + await state.delete() + await bot.send_message(message.chat.id, 'Your information has been cleared. Type /start to begin again.', reply_to_message_id=message.message_id) +# Handler for name input @bot.message_handler(state=MyStates.name) -async def name_get(message): - """ - State 1. Will process when user's state is MyStates.name. - """ - await bot.send_message(message.chat.id, f'Now write me a surname') - await bot.set_state(message.from_user.id, MyStates.surname, message.chat.id) - async with bot.retrieve_data(message.from_user.id, message.chat.id) as data: - data['name'] = message.text - - -@bot.message_handler(state=MyStates.surname) -async def ask_age(message): - """ - State 2. Will process when user's state is MyStates.surname. - """ - await bot.send_message(message.chat.id, "What is your age?") - await bot.set_state(message.from_user.id, MyStates.age, message.chat.id) - async with bot.retrieve_data(message.from_user.id, message.chat.id) as data: - data['surname'] = message.text - -# result +async def name_get(message: types.Message, state: StateContext): + await state.set(MyStates.age) + await bot.send_message(message.chat.id, "How old are you?", reply_to_message_id=message.message_id) + await state.add_data(name=message.text) + +# Handler for age input @bot.message_handler(state=MyStates.age, is_digit=True) -async def ready_for_answer(message): - """ - State 3. Will process when user's state is MyStates.age. - """ - async with bot.retrieve_data(message.from_user.id, message.chat.id) as data: - await bot.send_message(message.chat.id, "Ready, take a look:\nName: {name}\nSurname: {surname}\nAge: {age}".format(name=data['name'], surname=data['surname'], age=message.text), parse_mode="html") - await bot.delete_state(message.from_user.id, message.chat.id) - -#incorrect number +async def ask_color(message: types.Message, state: StateContext): + await state.set(MyStates.color) + await state.add_data(age=message.text) + + # Define reply keyboard for color selection + keyboard = types.ReplyKeyboardMarkup(row_width=2) + colors = ["Red", "Green", "Blue", "Yellow", "Purple", "Orange", "Other"] + buttons = [types.KeyboardButton(color) for color in colors] + keyboard.add(*buttons) + + await bot.send_message(message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + +# Handler for color input +@bot.message_handler(state=MyStates.color) +async def ask_hobby(message: types.Message, state: StateContext): + await state.set(MyStates.hobby) + await state.add_data(color=message.text) + + # Define reply keyboard for hobby selection + keyboard = types.ReplyKeyboardMarkup(row_width=2) + hobbies = ["Reading", "Traveling", "Gaming", "Cooking"] + buttons = [types.KeyboardButton(hobby) for hobby in hobbies] + keyboard.add(*buttons) + + await bot.send_message(message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + +# Handler for hobby input; use filters to ease validation +@bot.message_handler(state=MyStates.hobby, text=['Reading', 'Traveling', 'Gaming', 'Cooking']) +async def finish(message: types.Message, state: StateContext): + async with state.data() as data: + name = data.get('name') + age = data.get('age') + color = data.get('color') + hobby = message.text # Get the hobby from the message text + + # Provide a fun fact based on color + color_facts = { + "Red": "Red is often associated with excitement and passion.", + "Green": "Green is the color of nature and tranquility.", + "Blue": "Blue is known for its calming and serene effects.", + "Yellow": "Yellow is a cheerful color often associated with happiness.", + "Purple": "Purple signifies royalty and luxury.", + "Orange": "Orange is a vibrant color that stimulates enthusiasm.", + "Other": "Colors have various meanings depending on context." + } + color_fact = color_facts.get(color, "Colors have diverse meanings, and yours is unique!") + + msg = (f"Thank you for sharing! Here is a summary of your information:\n" + f"First Name: {name}\n" + f"Age: {age}\n" + f"Favorite Color: {color}\n" + f"Fun Fact about your color: {color_fact}\n" + f"Favorite Hobby: {hobby}") + + await bot.send_message(message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id) + await state.delete() + +# Handler for incorrect age input @bot.message_handler(state=MyStates.age, is_digit=False) -async def age_incorrect(message): - """ - Will process for wrong input when state is MyState.age - """ - await bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number') - -# register filters +async def age_incorrect(message: types.Message): + await bot.send_message(message.chat.id, 'Please enter a valid number for age.', reply_to_message_id=message.message_id) +# Add custom filters bot.add_custom_filter(asyncio_filters.StateFilter(bot)) bot.add_custom_filter(asyncio_filters.IsDigitFilter()) +bot.add_custom_filter(asyncio_filters.TextMatchFilter()) +# necessary for state parameter in handlers. +from telebot.states.aio.middleware import StateMiddleware +bot.setup_middleware(StateMiddleware(bot)) +# Start polling import asyncio -asyncio.run(bot.polling()) \ No newline at end of file +asyncio.run(bot.polling()) diff --git a/examples/custom_states.py b/examples/custom_states.py index a02761286..a488664b2 100644 --- a/examples/custom_states.py +++ b/examples/custom_states.py @@ -1,106 +1,112 @@ -import telebot # telebot - -from telebot import custom_filters -from telebot.handler_backends import State, StatesGroup #States - -# States storage +import telebot +from telebot import custom_filters, types +from telebot.states import State, StatesGroup +from telebot.states.sync.context import StateContext from telebot.storage import StateMemoryStorage +# Initialize the bot +state_storage = StateMemoryStorage() # don't use this in production; switch to redis +bot = telebot.TeleBot("TOKEN", state_storage=state_storage, + use_class_middlewares=True) -# Starting from version 4.4.0+, we support storages. -# StateRedisStorage -> Redis-based storage. -# StatePickleStorage -> Pickle-based storage. -# For redis, you will need to install redis. -# Pass host, db, password, or anything else, -# if you need to change config for redis. -# Pickle requires path. Default path is in folder .state-saves. -# If you were using older version of pytba for pickle, -# you need to migrate from old pickle to new by using -# StatePickleStorage().convert_old_to_new() - - - -# Now, you can pass storage to bot. -state_storage = StateMemoryStorage() # you can init here another storage - -bot = telebot.TeleBot("TOKEN", -state_storage=state_storage) - - -# States group. +# Define states class MyStates(StatesGroup): - # Just name variables differently - name = State() # creating instances of State class is enough from now - surname = State() + name = State() age = State() + color = State() + hobby = State() - - - +# Start command handler @bot.message_handler(commands=['start']) -def start_ex(message): - """ - Start command. Here we are starting state - """ - bot.set_state(message.from_user.id, MyStates.name, message.chat.id) - bot.send_message(message.chat.id, 'Hi, write me a name') - - -# Any state +def start_ex(message: types.Message, state: StateContext): + state.set(MyStates.name) + bot.send_message(message.chat.id, 'Hello! What is your first name?', reply_to_message_id=message.message_id) + +# Cancel command handler @bot.message_handler(state="*", commands=['cancel']) -def any_state(message): - """ - Cancel state - """ - bot.send_message(message.chat.id, "Your state was cancelled.") - bot.delete_state(message.from_user.id, message.chat.id) +def any_state(message: types.Message, state: StateContext): + state.delete() + bot.send_message(message.chat.id, 'Your information has been cleared. Type /start to begin again.', reply_to_message_id=message.message_id) +# Handler for name input @bot.message_handler(state=MyStates.name) -def name_get(message): - """ - State 1. Will process when user's state is MyStates.name. - """ - bot.send_message(message.chat.id, 'Now write me a surname') - bot.set_state(message.from_user.id, MyStates.surname, message.chat.id) - with bot.retrieve_data(message.from_user.id, message.chat.id) as data: - data['name'] = message.text - - -@bot.message_handler(state=MyStates.surname) -def ask_age(message): - """ - State 2. Will process when user's state is MyStates.surname. - """ - bot.send_message(message.chat.id, "What is your age?") - bot.set_state(message.from_user.id, MyStates.age, message.chat.id) - with bot.retrieve_data(message.from_user.id, message.chat.id) as data: - data['surname'] = message.text - -# result +def name_get(message: types.Message, state: StateContext): + state.set(MyStates.age) + bot.send_message(message.chat.id, "How old are you?", reply_to_message_id=message.message_id) + state.add_data(name=message.text) + +# Handler for age input @bot.message_handler(state=MyStates.age, is_digit=True) -def ready_for_answer(message): - """ - State 3. Will process when user's state is MyStates.age. - """ - with bot.retrieve_data(message.from_user.id, message.chat.id) as data: - msg = ("Ready, take a look:\n" - f"Name: {data['name']}\n" - f"Surname: {data['surname']}\n" - f"Age: {message.text}") - bot.send_message(message.chat.id, msg, parse_mode="html") - bot.delete_state(message.from_user.id, message.chat.id) - -#incorrect number +def ask_color(message: types.Message, state: StateContext): + state.set(MyStates.color) + state.add_data(age=message.text) + + # Define reply keyboard for color selection + keyboard = types.ReplyKeyboardMarkup(row_width=2) + colors = ["Red", "Green", "Blue", "Yellow", "Purple", "Orange", "Other"] + buttons = [types.KeyboardButton(color) for color in colors] + keyboard.add(*buttons) + + bot.send_message(message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + +# Handler for color input +@bot.message_handler(state=MyStates.color) +def ask_hobby(message: types.Message, state: StateContext): + state.set(MyStates.hobby) + state.add_data(color=message.text) + + # Define reply keyboard for hobby selection + keyboard = types.ReplyKeyboardMarkup(row_width=2) + hobbies = ["Reading", "Traveling", "Gaming", "Cooking"] + buttons = [types.KeyboardButton(hobby) for hobby in hobbies] + keyboard.add(*buttons) + + bot.send_message(message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + +# Handler for hobby input +@bot.message_handler(state=MyStates.hobby, text=['Reading', 'Traveling', 'Gaming', 'Cooking']) +def finish(message: types.Message, state: StateContext): + with state.data() as data: + name = data.get('name') + age = data.get('age') + color = data.get('color') + hobby = message.text # Get the hobby from the message text + + # Provide a fun fact based on color + color_facts = { + "Red": "Red is often associated with excitement and passion.", + "Green": "Green is the color of nature and tranquility.", + "Blue": "Blue is known for its calming and serene effects.", + "Yellow": "Yellow is a cheerful color often associated with happiness.", + "Purple": "Purple signifies royalty and luxury.", + "Orange": "Orange is a vibrant color that stimulates enthusiasm.", + "Other": "Colors have various meanings depending on context." + } + color_fact = color_facts.get(color, "Colors have diverse meanings, and yours is unique!") + + msg = (f"Thank you for sharing! Here is a summary of your information:\n" + f"First Name: {name}\n" + f"Age: {age}\n" + f"Favorite Color: {color}\n" + f"Fun Fact about your color: {color_fact}\n" + f"Favorite Hobby: {hobby}") + + bot.send_message(message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id) + state.delete() + +# Handler for incorrect age input @bot.message_handler(state=MyStates.age, is_digit=False) -def age_incorrect(message): - """ - Wrong response for MyStates.age - """ - bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number') - -# register filters +def age_incorrect(message: types.Message): + bot.send_message(message.chat.id, 'Please enter a valid number for age.', reply_to_message_id=message.message_id) +# Add custom filters bot.add_custom_filter(custom_filters.StateFilter(bot)) bot.add_custom_filter(custom_filters.IsDigitFilter()) +bot.add_custom_filter(custom_filters.TextMatchFilter()) + +# necessary for state parameter in handlers. +from telebot.states.sync.middleware import StateMiddleware +bot.setup_middleware(StateMiddleware(bot)) -bot.infinity_polling(skip_pending=True) +# Start polling +bot.infinity_polling() From 536ffa21f419ce91323ebe0723dc8bc26f70d145 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 25 Jul 2024 18:09:19 +0500 Subject: [PATCH 310/480] Added migrate_format to migrate from old format of states to new. Only redis as it should be used for production. --- telebot/asyncio_storage/redis_storage.py | 41 ++++++++++++++++++++++++ telebot/storage/redis_storage.py | 41 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index dea214daa..5c0c1bb0a 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -159,6 +159,47 @@ async def save(self, pipe, chat_id: int, user_id: int, data: dict, business_conn else: return False return True + + def migrate_format(self, bot_id: int, + prefix: Optional[str]="telebot_"): + """ + Migrate from old to new format of keys. + Run this function once to migrate all redis existing keys to new format. + + Starting from version 4.22.0, the format of keys has been changed: + :value + - Old format: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} + - New format: + {prefix}{separator}{bot_id}{separator}{business_connection_id}{separator}{message_thread_id}{separator}{chat_id}{separator}{user_id}: {'state': ..., 'data': {}} + + This function will help you to migrate from the old format to the new one in order to avoid data loss. + + :param bot_id: Bot ID; To get it, call a getMe request and grab the id from the response. + :type bot_id: int + + :param prefix: Prefix for keys, default is "telebot_"(old default value) + :type prefix: Optional[str] + """ + keys = self.redis.keys(f"{prefix}*") + + for key in keys: + old_key = key.decode('utf-8') + # old: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} + value = self.redis.get(old_key) + value = json.loads(value) + + chat_id = old_key[len(prefix):] + user_id = list(value.keys())[0] + state = value[user_id]['state'] + state_data = value[user_id]['data'] + + # set new format + new_key = self._get_key(int(chat_id), int(user_id), self.prefix, self.separator, bot_id=bot_id) + self.redis.hset(new_key, "state", state) + self.redis.hset(new_key, "data", json.dumps(state_data)) + + # delete old key + self.redis.delete(old_key) def __str__(self) -> str: # include some connection info diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 146ec2f63..3a81ac033 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -182,6 +182,47 @@ def save_action(pipe): self.redis.transaction(save_action, _key) return True + + def migrate_format(self, bot_id: int, + prefix: Optional[str]="telebot_"): + """ + Migrate from old to new format of keys. + Run this function once to migrate all redis existing keys to new format. + + Starting from version 4.22.0, the format of keys has been changed: + :value + - Old format: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} + - New format: + {prefix}{separator}{bot_id}{separator}{business_connection_id}{separator}{message_thread_id}{separator}{chat_id}{separator}{user_id}: {'state': ..., 'data': {}} + + This function will help you to migrate from the old format to the new one in order to avoid data loss. + + :param bot_id: Bot ID; To get it, call a getMe request and grab the id from the response. + :type bot_id: int + + :param prefix: Prefix for keys, default is "telebot_"(old default value) + :type prefix: Optional[str] + """ + keys = self.redis.keys(f"{prefix}*") + + for key in keys: + old_key = key.decode('utf-8') + # old: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} + value = self.redis.get(old_key) + value = json.loads(value) + + chat_id = old_key[len(prefix):] + user_id = list(value.keys())[0] + state = value[user_id]['state'] + state_data = value[user_id]['data'] + + # set new format + new_key = self._get_key(int(chat_id), int(user_id), self.prefix, self.separator, bot_id=bot_id) + self.redis.hset(new_key, "state", state) + self.redis.hset(new_key, "data", json.dumps(state_data)) + + # delete old key + self.redis.delete(old_key) def __str__(self) -> str: return f"StateRedisStorage({self.redis})" From d2485bf42827795a20f40cd3c3ff96e52df86f74 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 26 Jul 2024 11:57:52 +0500 Subject: [PATCH 311/480] Another approach to bot id --- telebot/__init__.py | 22 +++++++++++++--------- telebot/async_telebot.py | 20 +++++++++++--------- telebot/util.py | 18 +++++++++++++++++- tests/test_handler_backends.py | 2 +- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 07ae33181..d0ab64d5a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -152,9 +152,14 @@ class TeleBot: :param allow_sending_without_reply: Default value for allow_sending_without_reply, defaults to None :type allow_sending_without_reply: :obj:`bool`, optional - :param colorful_logs: Outputs colorful logs :type colorful_logs: :obj:`bool`, optional + + :param validate_token: Validate token, defaults to True; + :type validate_token: :obj:`bool`, optional + + :raises ImportError: If coloredlogs module is not installed and colorful_logs is True + :raises ValueError: If token is invalid """ def __init__( @@ -169,7 +174,7 @@ def __init__( protect_content: Optional[bool]=None, allow_sending_without_reply: Optional[bool]=None, colorful_logs: Optional[bool]=False, - token_check: Optional[bool]=True + validate_token: Optional[bool]=True ): # update-related @@ -186,11 +191,12 @@ def __init__( self.allow_sending_without_reply = allow_sending_without_reply self.webhook_listener = None self._user = None + self.bot_id: int = None - # token check - if token_check: - self._user = self.get_me() - self.bot_id = self._user.id + if validate_token: + util.validate_token(self.token) + + self.bot_id = util.extract_bot_id(self.token) # subject to change in future, unspecified # logs-related if colorful_logs: @@ -286,9 +292,7 @@ def __init__( self.threaded = threaded if self.threaded: self.worker_pool = util.ThreadPool(self, num_threads=num_threads) - - - + @property def user(self) -> types.User: """ diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 508aa6cb4..d60a4a090 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -117,8 +117,11 @@ class AsyncTeleBot: :param colorful_logs: Outputs colorful logs :type colorful_logs: :obj:`bool`, optional - :param token_check: Check token on start - :type token_check: :obj:`bool`, optional, defaults to True + :param validate_token: Validate token, defaults to True; + :type validate_token: :obj:`bool`, optional + + :raises ImportError: If coloredlogs module is not installed and colorful_logs is True + :raises ValueError: If token is invalid """ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[int]=None, @@ -129,7 +132,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ protect_content: Optional[bool]=None, allow_sending_without_reply: Optional[bool]=None, colorful_logs: Optional[bool]=False, - token_check: Optional[bool]=True) -> None: + validate_token: Optional[bool]=True) -> None: # update-related self.token = token @@ -186,15 +189,14 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.middlewares = [] self._user = None # set during polling - self.bot_id = None + self.bot_id: int = None - if token_check: - result = apihelper.get_me(token) - self._user = types.User.de_json(result) - self.bot_id = self._user.id + if validate_token: + util.validate_token(self.token) + + self.bot_id: int = util.extract_bot_id(self.token) # subject to change, unspecified - @property def user(self): return self._user diff --git a/telebot/util.py b/telebot/util.py index 295c0d1aa..c8ef526c5 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -686,6 +686,22 @@ def validate_web_app_data(token: str, raw_init_data: str): return hmac.new(secret_key.digest(), data_check_string.encode(), sha256).hexdigest() == init_data_hash +def validate_token(token) -> bool: + if any(char.isspace() for char in token): + raise ValueError('Token must not contain spaces') + + if ':' not in token: + raise ValueError('Token must contain a colon') + + if len(token.split(':')) != 2: + raise ValueError('Token must contain exactly 2 parts separated by a colon') + + return True + +def extract_bot_id(token) -> str: + return int(token.split(':')[0]) + + __all__ = ( "content_type_media", "content_type_service", "update_types", "WorkerThread", "AsyncTask", "CustomRequestResponse", @@ -696,5 +712,5 @@ def validate_web_app_data(token: str, raw_init_data: str): "split_string", "smart_split", "escape", "user_link", "quick_markup", "antiflood", "parse_web_app_data", "validate_web_app_data", "or_set", "or_clear", "orify", "OrEvent", "per_thread", - "webhook_google_functions" + "webhook_google_functions", "validate_token", "extract_bot_id" ) diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index f57200c1c..ad6ccaaad 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -19,7 +19,7 @@ @pytest.fixture() def telegram_bot(): - return telebot.TeleBot('', threaded=False, token_check=False) + return telebot.TeleBot('', threaded=False, validate_token=False) @pytest.fixture From dd0dfa98aa9a977827f62b078232941f981e372a Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 26 Jul 2024 11:59:26 +0500 Subject: [PATCH 312/480] fix tests --- tests/test_handler_backends.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index ad6ccaaad..b74d6fad0 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -19,7 +19,7 @@ @pytest.fixture() def telegram_bot(): - return telebot.TeleBot('', threaded=False, validate_token=False) + return telebot.TeleBot('1234:test', threaded=False) @pytest.fixture From 7f99176c034cd5e356f009dd2664a03cf67edf25 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 26 Jul 2024 13:00:39 +0500 Subject: [PATCH 313/480] fixed redis data bug on set_state --- telebot/asyncio_storage/redis_storage.py | 7 +++++++ telebot/storage/redis_storage.py | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index 5c0c1bb0a..69b18d5a1 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -95,7 +95,14 @@ async def set_state(self, pipe, chat_id: int, user_id: int, state: str, state = state.name _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + pipe.hget(_key, "data") + result = await pipe.execute() + data = result[0] + if data is None: + pipe.hset(_key, "data", json.dumps({})) + await pipe.hset(_key, "state", state) + return True async def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 3a81ac033..1d1413fa2 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -79,9 +79,17 @@ def set_state( def set_state_action(pipe): pipe.multi() - #pipe.hset(_key, mapping={"state": state, "data": "{}"}) + + data = pipe.hget(_key, "data") + result = pipe.execute() + data = result[0] + if data is None: + # If data is None, set it to an empty dictionary + data = {} + pipe.hset(_key, "data", json.dumps(data)) + pipe.hset(_key, "state", state) - + self.redis.transaction(set_state_action, _key) return True From 5c0ca1864b8921d2f6bdbcf71d9fbb3d5973dbb9 Mon Sep 17 00:00:00 2001 From: nypava Date: Sat, 27 Jul 2024 12:58:44 +0300 Subject: [PATCH 314/480] Add webapp example --- examples/webapp/bot.py | 19 +++++++++++ examples/webapp/webapp.html | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 examples/webapp/bot.py create mode 100644 examples/webapp/webapp.html diff --git a/examples/webapp/bot.py b/examples/webapp/bot.py new file mode 100644 index 000000000..310e25c5c --- /dev/null +++ b/examples/webapp/bot.py @@ -0,0 +1,19 @@ +from telebot import TeleBot +from telebot.types import ReplyKeyboardMarkup, KeyboardButton, WebAppInfo + +BOT_TOKEN = '' +WEB_URL = 'https://pytelegrambotminiapp.vercel.app/' # https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/webapp/webapp.html + +bot = TeleBot(BOT_TOKEN) + +@bot.message_handler(commands=["start"]) +def start(message): + reply_markup = ReplyKeyboardMarkup(resize_keyboard=True) + reply_markup.row(KeyboardButton("Start MiniApp", web_app=WebAppInfo(WEB_URL))) + bot.reply_to(message, "Click the button to start MiniApp", reply_markup=reply_markup) + +@bot.message_handler(content_types=['web_app_data']) +def web_app(message): + bot.reply_to(message, f'Your message is "{message.web_app_data.data}"') + +bot.infinity_polling() diff --git a/examples/webapp/webapp.html b/examples/webapp/webapp.html new file mode 100644 index 000000000..e2e953825 --- /dev/null +++ b/examples/webapp/webapp.html @@ -0,0 +1,63 @@ + + + + + + MiniApp example + + + + +
+ + +
+ + + + + + + From 3fec98c070f91b098766bef4968b283e26ce1556 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 27 Jul 2024 15:07:45 +0500 Subject: [PATCH 315/480] Code cleanup --- telebot/asyncio_storage/__init__.py | 12 +- telebot/asyncio_storage/base_storage.py | 66 ++++--- telebot/asyncio_storage/memory_storage.py | 183 +++++++++++++----- telebot/asyncio_storage/pickle_storage.py | 174 +++++++++++++---- telebot/asyncio_storage/redis_storage.py | 226 +++++++++++++++++----- telebot/states/__init__.py | 96 ++++++--- telebot/states/aio/__init__.py | 6 +- telebot/states/aio/context.py | 56 +++--- telebot/states/aio/middleware.py | 4 +- telebot/storage/__init__.py | 14 +- telebot/storage/base_storage.py | 66 ++++--- telebot/storage/memory_storage.py | 184 +++++++++++++----- telebot/storage/pickle_storage.py | 173 +++++++++++++---- telebot/storage/redis_storage.py | 186 +++++++++++++----- 14 files changed, 1054 insertions(+), 392 deletions(-) diff --git a/telebot/asyncio_storage/__init__.py b/telebot/asyncio_storage/__init__.py index 1f9d51650..82a8c817a 100644 --- a/telebot/asyncio_storage/__init__.py +++ b/telebot/asyncio_storage/__init__.py @@ -4,10 +4,10 @@ from telebot.asyncio_storage.base_storage import StateDataContext, StateStorageBase - - - __all__ = [ - 'StateStorageBase', 'StateDataContext', - 'StateMemoryStorage', 'StateRedisStorage', 'StatePickleStorage' -] \ No newline at end of file + "StateStorageBase", + "StateDataContext", + "StateMemoryStorage", + "StateRedisStorage", + "StatePickleStorage", +] diff --git a/telebot/asyncio_storage/base_storage.py b/telebot/asyncio_storage/base_storage.py index 6d06e7bfc..20d0b0587 100644 --- a/telebot/asyncio_storage/base_storage.py +++ b/telebot/asyncio_storage/base_storage.py @@ -1,5 +1,6 @@ import copy + class StateStorageBase: def __init__(self) -> None: pass @@ -15,30 +16,30 @@ async def get_data(self, chat_id, user_id): Get data for a user in a particular chat. """ raise NotImplementedError - + async def set_state(self, chat_id, user_id, state): """ Set state for a particular user. - ! Note that you should create a - record if it does not exist, and + ! Note that you should create a + record if it does not exist, and if a record with state already exists, you need to update a record. """ raise NotImplementedError - + async def delete_state(self, chat_id, user_id): """ Delete state for a particular user. """ raise NotImplementedError - + async def reset_data(self, chat_id, user_id): """ Reset data for a particular user in a chat. """ raise NotImplementedError - + async def get_state(self, chat_id, user_id): raise NotImplementedError @@ -51,16 +52,16 @@ def get_interactive_data(self, chat_id, user_id): async def save(self, chat_id, user_id, data): raise NotImplementedError - + def _get_key( - self, - chat_id: int, - user_id: int, - prefix: str, - separator: str, - business_connection_id: str=None, - message_thread_id: int=None, - bot_id: int=None + self, + chat_id: int, + user_id: int, + prefix: str, + separator: str, + business_connection_id: str = None, + message_thread_id: int = None, + bot_id: int = None, ) -> str: """ Convert parameters to a key. @@ -78,15 +79,20 @@ def _get_key( return separator.join(params) - - - - class StateDataContext: """ Class for data. """ - def __init__(self , obj, chat_id, user_id, business_connection_id=None, message_thread_id=None, bot_id=None, ): + + def __init__( + self, + obj, + chat_id, + user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): self.obj = obj self.data = None self.chat_id = chat_id @@ -95,13 +101,23 @@ def __init__(self , obj, chat_id, user_id, business_connection_id=None, message_ self.business_connection_id = business_connection_id self.message_thread_id = message_thread_id - - async def __aenter__(self): - data = await self.obj.get_data(chat_id=self.chat_id, user_id=self.user_id, business_connection_id=self.business_connection_id, - message_thread_id=self.message_thread_id, bot_id=self.bot_id) + data = await self.obj.get_data( + chat_id=self.chat_id, + user_id=self.user_id, + business_connection_id=self.business_connection_id, + message_thread_id=self.message_thread_id, + bot_id=self.bot_id, + ) self.data = copy.deepcopy(data) return self.data async def __aexit__(self, exc_type, exc_val, exc_tb): - return await self.obj.save(self.chat_id, self.user_id, self.data, self.business_connection_id, self.message_thread_id, self.bot_id) \ No newline at end of file + return await self.obj.save( + self.chat_id, + self.user_id, + self.data, + self.business_connection_id, + self.message_thread_id, + self.bot_id, + ) diff --git a/telebot/asyncio_storage/memory_storage.py b/telebot/asyncio_storage/memory_storage.py index 87449cace..e17d5fe8c 100644 --- a/telebot/asyncio_storage/memory_storage.py +++ b/telebot/asyncio_storage/memory_storage.py @@ -1,6 +1,7 @@ from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext from typing import Optional, Union + class StateMemoryStorage(StateStorageBase): """ Memory storage for states. @@ -19,72 +20,114 @@ class StateMemoryStorage(StateStorageBase): :type prefix: Optional[str] """ - def __init__(self, - separator: Optional[str]=":", - prefix: Optional[str]="telebot" - ) -> None: + def __init__( + self, separator: Optional[str] = ":", prefix: Optional[str] = "telebot" + ) -> None: self.separator = separator self.prefix = prefix if not self.prefix: raise ValueError("Prefix cannot be empty") - - self.data = {} # key: telebot:bot_id:business_connection_id:message_thread_id:chat_id:user_id - async def set_state( - self, chat_id: int, user_id: int, state: str, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self.data = ( + {} + ) # key: telebot:bot_id:business_connection_id:message_thread_id:chat_id:user_id + async def set_state( + self, + chat_id: int, + user_id: int, + state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: if hasattr(state, "name"): state = state.name _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: self.data[_key] = {"state": state, "data": {}} else: self.data[_key]["state"] = state - + return True - + async def get_state( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> Union[str, None]: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: return None - + return self.data[_key]["state"] - + async def delete_state( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) - + if self.data.get(_key) is None: return False - + del self.data[_key] return True - - + async def set_data( - self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, - bot_id: Optional[int]=None) -> bool: - + self, + chat_id: int, + user_id: int, + key: str, + value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: + _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: @@ -92,57 +135,91 @@ async def set_data( self.data[_key]["data"][key] = value return True - async def get_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> dict: - + _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) return self.data.get(_key, {}).get("data", {}) - + async def reset_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: - + _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: return False self.data[_key]["data"] = {} return True - + def get_interactive_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> Optional[dict]: return StateDataContext( - self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id + self, + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, ) - + async def save( - self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + data: dict, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, - message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: return False self.data[_key]["data"] = data return True - + def __str__(self) -> str: return f"" - - - diff --git a/telebot/asyncio_storage/pickle_storage.py b/telebot/asyncio_storage/pickle_storage.py index 0506d4703..723672034 100644 --- a/telebot/asyncio_storage/pickle_storage.py +++ b/telebot/asyncio_storage/pickle_storage.py @@ -1,4 +1,3 @@ - aiofiles_installed = True try: import aiofiles @@ -12,12 +11,15 @@ from telebot.asyncio_storage.base_storage import StateStorageBase, StateDataContext + def with_lock(func: Callable) -> Callable: async def wrapper(self, *args, **kwargs): async with self.lock: return await func(self, *args, **kwargs) + return wrapper + class StatePickleStorage(StateStorageBase): """ State storage based on pickle file. @@ -27,7 +29,7 @@ class StatePickleStorage(StateStorageBase): This storage is not recommended for production use. Data may be corrupted. If you face a case where states do not work as expected, try to use another storage. - + .. code-block:: python3 storage = StatePickleStorage() @@ -42,9 +44,14 @@ class StatePickleStorage(StateStorageBase): :param separator: Separator for keys, default is ":". :type separator: Optional[str] """ - def __init__(self, file_path: str = "./.state-save/states.pkl", - prefix='telebot', separator: Optional[str] = ":") -> None: - + + def __init__( + self, + file_path: str = "./.state-save/states.pkl", + prefix="telebot", + separator: Optional[str] = ":", + ) -> None: + if not aiofiles_installed: raise ImportError("Please install aiofiles using `pip install aiofiles`") @@ -55,12 +62,12 @@ def __init__(self, file_path: str = "./.state-save/states.pkl", self.create_dir() async def _read_from_file(self) -> dict: - async with aiofiles.open(self.file_path, 'rb') as f: + async with aiofiles.open(self.file_path, "rb") as f: data = await f.read() return pickle.loads(data) async def _write_to_file(self, data: dict) -> None: - async with aiofiles.open(self.file_path, 'wb') as f: + async with aiofiles.open(self.file_path, "wb") as f: await f.write(pickle.dumps(data)) def create_dir(self): @@ -70,16 +77,27 @@ def create_dir(self): dirs, filename = os.path.split(self.file_path) os.makedirs(dirs, exist_ok=True) if not os.path.isfile(self.file_path): - with open(self.file_path,'wb') as file: + with open(self.file_path, "wb") as file: pickle.dump({}, file) - @with_lock - async def set_state(self, chat_id: int, user_id: int, state: str, - business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, - bot_id: Optional[int] = None) -> bool: + async def set_state( + self, + chat_id: int, + user_id: int, + state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() if _key not in data: @@ -90,19 +108,43 @@ async def set_state(self, chat_id: int, user_id: int, state: str, return True @with_lock - async def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Union[str, None]: + async def get_state( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> Union[str, None]: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() return data.get(_key, {}).get("state") @with_lock - async def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + async def delete_state( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() if _key in data: @@ -112,11 +154,24 @@ async def delete_state(self, chat_id: int, user_id: int, business_connection_id: return False @with_lock - async def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, - bot_id: Optional[int] = None) -> bool: + async def set_data( + self, + chat_id: int, + user_id: int, + key: str, + value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() state_data = data.get(_key, {}) @@ -129,19 +184,43 @@ async def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, return True @with_lock - async def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> dict: + async def get_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> dict: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() return data.get(_key, {}).get("data", {}) @with_lock - async def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + async def reset_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() if _key in data: @@ -150,18 +229,41 @@ async def reset_data(self, chat_id: int, user_id: int, business_connection_id: O return True return False - def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Optional[dict]: + def get_interactive_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> Optional[dict]: return StateDataContext( - self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id + self, + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, ) @with_lock - async def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + async def save( + self, + chat_id: int, + user_id: int, + data: dict, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = await self._read_from_file() data[_key]["data"] = data diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index 69b18d5a1..eccff5c30 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -1,4 +1,3 @@ - redis_installed = True try: import redis @@ -17,8 +16,10 @@ def async_with_lock(func: Callable[..., Coroutine]) -> Callable[..., Coroutine]: async def wrapper(self, *args, **kwargs): async with self.lock: return await func(self, *args, **kwargs) + return wrapper + def async_with_pipeline(func: Callable[..., Coroutine]) -> Callable[..., Coroutine]: async def wrapper(self, *args, **kwargs): async with self.redis.pipeline() as pipe: @@ -26,8 +27,10 @@ async def wrapper(self, *args, **kwargs): result = await func(self, pipe, *args, **kwargs) await pipe.execute() return result + return wrapper + class StateRedisStorage(StateStorageBase): """ State storage based on Redis. @@ -62,16 +65,22 @@ class StateRedisStorage(StateStorageBase): :type separator: Optional[str] """ - def __init__(self, host='localhost', port=6379, db=0, password=None, - prefix='telebot', - redis_url=None, - connection_pool: 'ConnectionPool'=None, - separator: Optional[str] = ":", - ) -> None: - + + def __init__( + self, + host="localhost", + port=6379, + db=0, + password=None, + prefix="telebot", + redis_url=None, + connection_pool: "ConnectionPool" = None, + separator: Optional[str] = ":", + ) -> None: + if not redis_installed: raise ImportError("Please install redis using `pip install redis`") - + self.separator = separator self.prefix = prefix if not self.prefix: @@ -83,46 +92,105 @@ def __init__(self, host='localhost', port=6379, db=0, password=None, self.redis = Redis(connection_pool=connection_pool) else: self.redis = Redis(host=host, port=port, db=db, password=password) - + self.lock = asyncio.Lock() @async_with_lock @async_with_pipeline - async def set_state(self, pipe, chat_id: int, user_id: int, state: str, - business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + async def set_state( + self, + pipe, + chat_id: int, + user_id: int, + state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: if hasattr(state, "name"): state = state.name - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) pipe.hget(_key, "data") result = await pipe.execute() data = result[0] if data is None: pipe.hset(_key, "data", json.dumps({})) - + await pipe.hset(_key, "state", state) - + return True - async def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Union[str, None]: - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + async def get_state( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> Union[str, None]: + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) state_bytes = await self.redis.hget(_key, "state") - return state_bytes.decode('utf-8') if state_bytes else None - - async def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + return state_bytes.decode("utf-8") if state_bytes else None + + async def delete_state( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) result = await self.redis.delete(_key) return result > 0 @async_with_lock @async_with_pipeline - async def set_data(self, pipe, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, - bot_id: Optional[int] = None) -> bool: - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + async def set_data( + self, + pipe, + chat_id: int, + user_id: int, + key: str, + value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) data = await pipe.hget(_key, "data") data = await pipe.execute() data = data[0] @@ -134,41 +202,97 @@ async def set_data(self, pipe, chat_id: int, user_id: int, key: str, value: Unio await pipe.hset(_key, "data", json.dumps(data)) return True - async def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> dict: - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + async def get_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> dict: + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) data = await self.redis.hget(_key, "data") return json.loads(data) if data else {} @async_with_lock @async_with_pipeline - async def reset_data(self, pipe, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + async def reset_data( + self, + pipe, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) if await pipe.exists(_key): await pipe.hset(_key, "data", "{}") else: return False return True - def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Optional[dict]: - return StateDataContext(self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id) + def get_interactive_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> Optional[dict]: + return StateDataContext( + self, + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, + ) @async_with_lock @async_with_pipeline - async def save(self, pipe, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: - _key = self._get_key(chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id) + async def save( + self, + pipe, + chat_id: int, + user_id: int, + data: dict, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: + _key = self._get_key( + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, + ) if await pipe.exists(_key): await pipe.hset(_key, "data", json.dumps(data)) else: return False return True - - def migrate_format(self, bot_id: int, - prefix: Optional[str]="telebot_"): + + def migrate_format(self, bot_id: int, prefix: Optional[str] = "telebot_"): """ Migrate from old to new format of keys. Run this function once to migrate all redis existing keys to new format. @@ -188,20 +312,22 @@ def migrate_format(self, bot_id: int, :type prefix: Optional[str] """ keys = self.redis.keys(f"{prefix}*") - + for key in keys: - old_key = key.decode('utf-8') + old_key = key.decode("utf-8") # old: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} value = self.redis.get(old_key) value = json.loads(value) - chat_id = old_key[len(prefix):] + chat_id = old_key[len(prefix) :] user_id = list(value.keys())[0] - state = value[user_id]['state'] - state_data = value[user_id]['data'] + state = value[user_id]["state"] + state_data = value[user_id]["data"] # set new format - new_key = self._get_key(int(chat_id), int(user_id), self.prefix, self.separator, bot_id=bot_id) + new_key = self._get_key( + int(chat_id), int(user_id), self.prefix, self.separator, bot_id=bot_id + ) self.redis.hset(new_key, "state", state) self.redis.hset(new_key, "data", json.dumps(state_data)) diff --git a/telebot/states/__init__.py b/telebot/states/__init__.py index 015f135e4..2491608ee 100644 --- a/telebot/states/__init__.py +++ b/telebot/states/__init__.py @@ -1,8 +1,10 @@ """ Contains classes for states and state groups. """ + from telebot import types + class State: """ Class representing a state. @@ -12,9 +14,11 @@ class State: class MyStates(StatesGroup): my_state = State() # returns my_state:State string. """ + def __init__(self) -> None: self.name: str = None self.group: StatesGroup = None + def __str__(self) -> str: return f"<{self.name}>" @@ -28,12 +32,17 @@ class StatesGroup: class MyStates(StatesGroup): my_state = State() # returns my_state:State string. """ + def __init_subclass__(cls) -> None: state_list = [] for name, value in cls.__dict__.items(): - if not name.startswith('__') and not callable(value) and isinstance(value, State): + if ( + not name.startswith("__") + and not callable(value) + and isinstance(value, State) + ): # change value of that variable - value.name = ':'.join((cls.__name__, name)) + value.name = ":".join((cls.__name__, name)) value.group = cls state_list.append(value) cls._state_list = state_list @@ -42,41 +51,78 @@ def __init_subclass__(cls) -> None: def state_list(self): return self._state_list + def resolve_context(message, bot_id: int) -> tuple: # chat_id, user_id, business_connection_id, bot_id, message_thread_id - + # message, edited_message, channel_post, edited_channel_post, business_message, edited_business_message if isinstance(message, types.Message): - return (message.chat.id, message.from_user.id, message.business_connection_id, bot_id, - message.message_thread_id if message.is_topic_message else None) - elif isinstance(message, types.CallbackQuery): # callback_query - return (message.message.chat.id, message.from_user.id, message.message.business_connection_id, bot_id, - message.message.message_thread_id if message.message.is_topic_message else None) - elif isinstance(message, types.BusinessConnection): # business_connection + return ( + message.chat.id, + message.from_user.id, + message.business_connection_id, + bot_id, + message.message_thread_id if message.is_topic_message else None, + ) + elif isinstance(message, types.CallbackQuery): # callback_query + return ( + message.message.chat.id, + message.from_user.id, + message.message.business_connection_id, + bot_id, + ( + message.message.message_thread_id + if message.message.is_topic_message + else None + ), + ) + elif isinstance(message, types.BusinessConnection): # business_connection return (message.user_chat_id, message.user.id, message.id, bot_id, None) - elif isinstance(message, types.BusinessMessagesDeleted): # deleted_business_messages - return (message.chat.id, message.chat.id, message.business_connection_id, bot_id, None) - elif isinstance(message, types.MessageReactionUpdated): # message_reaction + elif isinstance( + message, types.BusinessMessagesDeleted + ): # deleted_business_messages + return ( + message.chat.id, + message.chat.id, + message.business_connection_id, + bot_id, + None, + ) + elif isinstance(message, types.MessageReactionUpdated): # message_reaction return (message.chat.id, message.user.id, None, bot_id, None) - elif isinstance(message, types.MessageReactionCountUpdated): # message_reaction_count + elif isinstance( + message, types.MessageReactionCountUpdated + ): # message_reaction_count return (message.chat.id, None, None, bot_id, None) - elif isinstance(message, types.InlineQuery): # inline_query + elif isinstance(message, types.InlineQuery): # inline_query return (None, message.from_user.id, None, bot_id, None) - elif isinstance(message, types.ChosenInlineResult): # chosen_inline_result + elif isinstance(message, types.ChosenInlineResult): # chosen_inline_result return (None, message.from_user.id, None, bot_id, None) - elif isinstance(message, types.ShippingQuery): # shipping_query + elif isinstance(message, types.ShippingQuery): # shipping_query return (None, message.from_user.id, None, bot_id, None) - elif isinstance(message, types.PreCheckoutQuery): # pre_checkout_query + elif isinstance(message, types.PreCheckoutQuery): # pre_checkout_query return (None, message.from_user.id, None, bot_id, None) - elif isinstance(message, types.PollAnswer): # poll_answer + elif isinstance(message, types.PollAnswer): # poll_answer return (None, message.user.id, None, bot_id, None) - elif isinstance(message, types.ChatMemberUpdated): # chat_member # my_chat_member + elif isinstance(message, types.ChatMemberUpdated): # chat_member # my_chat_member return (message.chat.id, message.from_user.id, None, bot_id, None) - elif isinstance(message, types.ChatJoinRequest): # chat_join_request + elif isinstance(message, types.ChatJoinRequest): # chat_join_request return (message.chat.id, message.from_user.id, None, bot_id, None) - elif isinstance(message, types.ChatBoostRemoved): # removed_chat_boost - return (message.chat.id, message.source.user.id if message.source else None, None, bot_id, None) - elif isinstance(message, types.ChatBoostUpdated): # chat_boost - return (message.chat.id, message.boost.source.user.id if message.boost.source else None, None, bot_id, None) + elif isinstance(message, types.ChatBoostRemoved): # removed_chat_boost + return ( + message.chat.id, + message.source.user.id if message.source else None, + None, + bot_id, + None, + ) + elif isinstance(message, types.ChatBoostUpdated): # chat_boost + return ( + message.chat.id, + message.boost.source.user.id if message.boost.source else None, + None, + bot_id, + None, + ) else: - pass # not yet supported :( \ No newline at end of file + pass # not yet supported :( diff --git a/telebot/states/aio/__init__.py b/telebot/states/aio/__init__.py index 60f9ea2b7..14ef19536 100644 --- a/telebot/states/aio/__init__.py +++ b/telebot/states/aio/__init__.py @@ -2,6 +2,6 @@ from .middleware import StateMiddleware __all__ = [ - 'StateContext', - 'StateMiddleware', -] \ No newline at end of file + "StateContext", + "StateMiddleware", +] diff --git a/telebot/states/aio/context.py b/telebot/states/aio/context.py index 956ca6837..4c9ad61a3 100644 --- a/telebot/states/aio/context.py +++ b/telebot/states/aio/context.py @@ -6,8 +6,7 @@ from typing import Union - -class StateContext(): +class StateContext: """ Class representing a state context. @@ -21,7 +20,7 @@ async def start_ex(message: types.Message, state_context: StateContext): await bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) # also, state_context.data(), .add_data(), .reset_data(), .delete() methods available. """ - + def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: self.message: Union[Message, CallbackQuery] = message self.bot: AsyncTeleBot = bot @@ -42,7 +41,9 @@ async def start_ex(message: types.Message, state_context: StateContext): await bot.send_message(message.chat.id, 'Hi, write me a name', reply_to_message_id=message.message_id) """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = ( + resolve_context(self.message, self.bot.bot_id) + ) if isinstance(state, State): state = state.name return await self.bot.set_state( @@ -51,9 +52,9 @@ async def start_ex(message: types.Message, state_context: StateContext): state=state, business_connection_id=business_connection_id, bot_id=bot_id, - message_thread_id=message_thread_id + message_thread_id=message_thread_id, ) - + async def get(self) -> str: """ Get current state for current user. @@ -62,67 +63,75 @@ async def get(self) -> str: :rtype: str """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = ( + resolve_context(self.message, self.bot.bot_id) + ) return await self.bot.get_state( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, bot_id=bot_id, - message_thread_id=message_thread_id + message_thread_id=message_thread_id, ) - + async def delete(self) -> bool: """ Deletes state and data for current user. .. warning:: - + This method deletes state and associated data for current user. """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = ( + resolve_context(self.message, self.bot.bot_id) + ) return await self.bot.delete_state( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, bot_id=bot_id, - message_thread_id=message_thread_id + message_thread_id=message_thread_id, ) - + async def reset_data(self) -> bool: """ - Reset data for current user. + Reset data for current user. State will not be changed. """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = ( + resolve_context(self.message, self.bot.bot_id) + ) return await self.bot.reset_data( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, bot_id=bot_id, - message_thread_id=message_thread_id + message_thread_id=message_thread_id, ) - + def data(self) -> dict: """ Get data for current user. .. code-block:: python3 - + with state_context.data() as data: print(data) data['name'] = 'John' """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = ( + resolve_context(self.message, self.bot.bot_id) + ) return self.bot.retrieve_data( chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, bot_id=bot_id, - message_thread_id=message_thread_id + message_thread_id=message_thread_id, ) - + async def add_data(self, **kwargs) -> None: """ Add data for current user. @@ -131,7 +140,9 @@ async def add_data(self, **kwargs) -> None: :type kwargs: dict """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(self.message, self.bot.bot_id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = ( + resolve_context(self.message, self.bot.bot_id) + ) return await self.bot.add_data( chat_id=chat_id, user_id=user_id, @@ -140,4 +151,3 @@ async def add_data(self, **kwargs) -> None: message_thread_id=message_thread_id, **kwargs ) - \ No newline at end of file diff --git a/telebot/states/aio/middleware.py b/telebot/states/aio/middleware.py index 546b29067..675b7b462 100644 --- a/telebot/states/aio/middleware.py +++ b/telebot/states/aio/middleware.py @@ -14,8 +14,8 @@ def __init__(self, bot: AsyncTeleBot) -> None: async def pre_process(self, message, data): state_context = StateContext(message, self.bot) - data['state_context'] = state_context - data['state'] = state_context # 2 ways to access state context + data["state_context"] = state_context + data["state"] = state_context # 2 ways to access state context async def post_process(self, message, data, exception): pass diff --git a/telebot/storage/__init__.py b/telebot/storage/__init__.py index 954c1b31d..bb3dd7f07 100644 --- a/telebot/storage/__init__.py +++ b/telebot/storage/__init__.py @@ -1,13 +1,13 @@ from telebot.storage.memory_storage import StateMemoryStorage from telebot.storage.redis_storage import StateRedisStorage from telebot.storage.pickle_storage import StatePickleStorage -from telebot.storage.base_storage import StateDataContext,StateStorageBase - - - +from telebot.storage.base_storage import StateDataContext, StateStorageBase __all__ = [ - 'StateStorageBase', 'StateDataContext', - 'StateMemoryStorage', 'StateRedisStorage', 'StatePickleStorage' -] \ No newline at end of file + "StateStorageBase", + "StateDataContext", + "StateMemoryStorage", + "StateRedisStorage", + "StatePickleStorage", +] diff --git a/telebot/storage/base_storage.py b/telebot/storage/base_storage.py index 25a6c6b04..9956c7ab9 100644 --- a/telebot/storage/base_storage.py +++ b/telebot/storage/base_storage.py @@ -1,5 +1,6 @@ import copy + class StateStorageBase: def __init__(self) -> None: pass @@ -15,30 +16,30 @@ def get_data(self, chat_id, user_id): Get data for a user in a particular chat. """ raise NotImplementedError - + def set_state(self, chat_id, user_id, state): """ Set state for a particular user. - ! Note that you should create a - record if it does not exist, and + ! Note that you should create a + record if it does not exist, and if a record with state already exists, you need to update a record. """ raise NotImplementedError - + def delete_state(self, chat_id, user_id): """ Delete state for a particular user. """ raise NotImplementedError - + def reset_data(self, chat_id, user_id): """ Reset data for a particular user in a chat. """ raise NotImplementedError - + def get_state(self, chat_id, user_id): raise NotImplementedError @@ -47,16 +48,16 @@ def get_interactive_data(self, chat_id, user_id): def save(self, chat_id, user_id, data): raise NotImplementedError - + def _get_key( - self, - chat_id: int, - user_id: int, - prefix: str, - separator: str, - business_connection_id: str=None, - message_thread_id: int=None, - bot_id: int=None + self, + chat_id: int, + user_id: int, + prefix: str, + separator: str, + business_connection_id: str = None, + message_thread_id: int = None, + bot_id: int = None, ) -> str: """ Convert parameters to a key. @@ -74,18 +75,28 @@ def _get_key( return separator.join(params) - - - - class StateDataContext: """ Class for data. """ - def __init__(self , obj, chat_id, user_id, business_connection_id=None, message_thread_id=None, bot_id=None, ): + + def __init__( + self, + obj, + chat_id, + user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): self.obj = obj - res = obj.get_data(chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id) + res = obj.get_data( + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, + ) self.data = copy.deepcopy(res) self.chat_id = chat_id self.user_id = user_id @@ -93,10 +104,15 @@ def __init__(self , obj, chat_id, user_id, business_connection_id=None, message_ self.business_connection_id = business_connection_id self.message_thread_id = message_thread_id - - def __enter__(self): return self.data def __exit__(self, exc_type, exc_val, exc_tb): - return self.obj.save(self.chat_id, self.user_id, self.data, self.business_connection_id, self.message_thread_id, self.bot_id) \ No newline at end of file + return self.obj.save( + self.chat_id, + self.user_id, + self.data, + self.business_connection_id, + self.message_thread_id, + self.bot_id, + ) diff --git a/telebot/storage/memory_storage.py b/telebot/storage/memory_storage.py index dc88bcebc..21266632c 100644 --- a/telebot/storage/memory_storage.py +++ b/telebot/storage/memory_storage.py @@ -1,6 +1,7 @@ from telebot.storage.base_storage import StateStorageBase, StateDataContext from typing import Optional, Union + class StateMemoryStorage(StateStorageBase): """ Memory storage for states. @@ -18,72 +19,115 @@ class StateMemoryStorage(StateStorageBase): :param prefix: Prefix for keys, default is "telebot". :type prefix: Optional[str] """ - def __init__(self, - separator: Optional[str]=":", - prefix: Optional[str]="telebot" - ) -> None: + + def __init__( + self, separator: Optional[str] = ":", prefix: Optional[str] = "telebot" + ) -> None: self.separator = separator self.prefix = prefix if not self.prefix: raise ValueError("Prefix cannot be empty") - - self.data = {} # key: telebot:bot_id:business_connection_id:message_thread_id:chat_id:user_id - def set_state( - self, chat_id: int, user_id: int, state: str, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self.data = ( + {} + ) # key: telebot:bot_id:business_connection_id:message_thread_id:chat_id:user_id + def set_state( + self, + chat_id: int, + user_id: int, + state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: if hasattr(state, "name"): state = state.name _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: self.data[_key] = {"state": state, "data": {}} else: self.data[_key]["state"] = state - + return True - + def get_state( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> Union[str, None]: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: return None - + return self.data[_key]["state"] - + def delete_state( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) - + if self.data.get(_key) is None: return False - + del self.data[_key] return True - - + def set_data( - self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, - bot_id: Optional[int]=None) -> bool: - + self, + chat_id: int, + user_id: int, + key: str, + value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: + _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: @@ -91,57 +135,91 @@ def set_data( self.data[_key]["data"][key] = value return True - def get_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> dict: - + _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) return self.data.get(_key, {}).get("data", {}) - + def reset_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: - + _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: return False self.data[_key]["data"] = {} return True - + def get_interactive_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> Optional[dict]: return StateDataContext( - self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id + self, + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, ) - + def save( - self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, bot_id: Optional[int]=None + self, + chat_id: int, + user_id: int, + data: dict, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, - message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) if self.data.get(_key) is None: return False self.data[_key]["data"] = data return True - + def __str__(self) -> str: return f"" - - - diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index fc8dc3289..e11a05043 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -4,12 +4,15 @@ from typing import Optional, Union, Callable from telebot.storage.base_storage import StateStorageBase, StateDataContext + def with_lock(func: Callable) -> Callable: def wrapper(self, *args, **kwargs): with self.lock: return func(self, *args, **kwargs) + return wrapper + class StatePickleStorage(StateStorageBase): """ State storage based on pickle file. @@ -19,7 +22,7 @@ class StatePickleStorage(StateStorageBase): This storage is not recommended for production use. Data may be corrupted. If you face a case where states do not work as expected, try to use another storage. - + .. code-block:: python3 storage = StatePickleStorage() @@ -35,8 +38,12 @@ class StatePickleStorage(StateStorageBase): :type separator: Optional[str] """ - def __init__(self, file_path: str = "./.state-save/states.pkl", - prefix='telebot', separator: Optional[str] = ":") -> None: + def __init__( + self, + file_path: str = "./.state-save/states.pkl", + prefix="telebot", + separator: Optional[str] = ":", + ) -> None: self.file_path = file_path self.prefix = prefix self.separator = separator @@ -45,11 +52,11 @@ def __init__(self, file_path: str = "./.state-save/states.pkl", self.create_dir() def _read_from_file(self) -> dict: - with open(self.file_path, 'rb') as f: + with open(self.file_path, "rb") as f: return pickle.load(f) def _write_to_file(self, data: dict) -> None: - with open(self.file_path, 'wb') as f: + with open(self.file_path, "wb") as f: pickle.dump(data, f) def create_dir(self): @@ -59,15 +66,27 @@ def create_dir(self): dirs, filename = os.path.split(self.file_path) os.makedirs(dirs, exist_ok=True) if not os.path.isfile(self.file_path): - with open(self.file_path,'wb') as file: + with open(self.file_path, "wb") as file: pickle.dump({}, file) @with_lock - def set_state(self, chat_id: int, user_id: int, state: str, - business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, - bot_id: Optional[int] = None) -> bool: + def set_state( + self, + chat_id: int, + user_id: int, + state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() if _key not in data: @@ -78,19 +97,43 @@ def set_state(self, chat_id: int, user_id: int, state: str, return True @with_lock - def get_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Union[str, None]: + def get_state( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> Union[str, None]: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() return data.get(_key, {}).get("state") - + @with_lock - def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + def delete_state( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() if _key in data: @@ -100,11 +143,24 @@ def delete_state(self, chat_id: int, user_id: int, business_connection_id: Optio return False @with_lock - def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, - bot_id: Optional[int] = None) -> bool: + def set_data( + self, + chat_id: int, + user_id: int, + key: str, + value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() state_data = data.get(_key, {}) @@ -117,19 +173,43 @@ def set_data(self, chat_id: int, user_id: int, key: str, value: Union[str, int, return True @with_lock - def get_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> dict: + def get_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> dict: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() return data.get(_key, {}).get("data", {}) @with_lock - def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + def reset_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() if _key in data: @@ -138,23 +218,46 @@ def reset_data(self, chat_id: int, user_id: int, business_connection_id: Optiona return True return False - def get_interactive_data(self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> Optional[dict]: + def get_interactive_data( + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> Optional[dict]: return StateDataContext( - self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id + self, + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, ) @with_lock - def save(self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None) -> bool: + def save( + self, + chat_id: int, + user_id: int, + data: dict, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, + ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self._read_from_file() data[_key]["data"] = data self._write_to_file(data) return True - + def __str__(self) -> str: return f"StatePickleStorage({self.file_path}, {self.prefix})" diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 1d1413fa2..19f5c2cd5 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -8,6 +8,7 @@ except ImportError: redis_installed = False + class StateRedisStorage(StateStorageBase): """ State storage based on Redis. @@ -42,39 +43,56 @@ class StateRedisStorage(StateStorageBase): :type separator: Optional[str] """ - def __init__(self, host='localhost', port=6379, db=0, password=None, - prefix='telebot', - redis_url=None, - connection_pool: 'redis.ConnectionPool'=None, - separator: Optional[str]=":", - ) -> None: - + + def __init__( + self, + host="localhost", + port=6379, + db=0, + password=None, + prefix="telebot", + redis_url=None, + connection_pool: "redis.ConnectionPool" = None, + separator: Optional[str] = ":", + ) -> None: + if not redis_installed: - raise ImportError("Redis is not installed. Please install it via pip install redis") + raise ImportError( + "Redis is not installed. Please install it via pip install redis" + ) self.separator = separator self.prefix = prefix if not self.prefix: raise ValueError("Prefix cannot be empty") - + if redis_url: self.redis = redis.Redis.from_url(redis_url) elif connection_pool: self.redis = redis.Redis(connection_pool=connection_pool) else: self.redis = redis.Redis(host=host, port=port, db=db, password=password) - def set_state( - self, chat_id: int, user_id: int, state: str, - business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + state: str, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: if hasattr(state, "name"): state = state.name _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) def set_state_action(pipe): @@ -89,36 +107,67 @@ def set_state_action(pipe): pipe.hset(_key, "data", json.dumps(data)) pipe.hset(_key, "state", state) - + self.redis.transaction(set_state_action, _key) return True def get_state( - self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> Union[str, None]: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) state_bytes = self.redis.hget(_key, "state") - return state_bytes.decode('utf-8') if state_bytes else None + return state_bytes.decode("utf-8") if state_bytes else None def delete_state( - self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) return self.redis.delete(_key) > 0 def set_data( - self, chat_id: int, user_id: int, key: str, value: Union[str, int, float, dict], - business_connection_id: Optional[str] = None, message_thread_id: Optional[int] = None, - bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + key: str, + value: Union[str, int, float, dict], + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) def set_data_action(pipe): @@ -136,21 +185,41 @@ def set_data_action(pipe): return True def get_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> dict: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) data = self.redis.hget(_key, "data") return json.loads(data) if data else {} def reset_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) def reset_data_action(pipe): @@ -164,21 +233,39 @@ def reset_data_action(pipe): return True def get_interactive_data( - self, chat_id: int, user_id: int, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> Optional[dict]: return StateDataContext( - self, chat_id=chat_id, user_id=user_id, business_connection_id=business_connection_id, - message_thread_id=message_thread_id, bot_id=bot_id + self, + chat_id=chat_id, + user_id=user_id, + business_connection_id=business_connection_id, + message_thread_id=message_thread_id, + bot_id=bot_id, ) def save( - self, chat_id: int, user_id: int, data: dict, business_connection_id: Optional[str] = None, - message_thread_id: Optional[int] = None, bot_id: Optional[int] = None + self, + chat_id: int, + user_id: int, + data: dict, + business_connection_id: Optional[str] = None, + message_thread_id: Optional[int] = None, + bot_id: Optional[int] = None, ) -> bool: _key = self._get_key( - chat_id, user_id, self.prefix, self.separator, business_connection_id, - message_thread_id, bot_id + chat_id, + user_id, + self.prefix, + self.separator, + business_connection_id, + message_thread_id, + bot_id, ) def save_action(pipe): @@ -190,9 +277,8 @@ def save_action(pipe): self.redis.transaction(save_action, _key) return True - - def migrate_format(self, bot_id: int, - prefix: Optional[str]="telebot_"): + + def migrate_format(self, bot_id: int, prefix: Optional[str] = "telebot_"): """ Migrate from old to new format of keys. Run this function once to migrate all redis existing keys to new format. @@ -212,20 +298,22 @@ def migrate_format(self, bot_id: int, :type prefix: Optional[str] """ keys = self.redis.keys(f"{prefix}*") - + for key in keys: - old_key = key.decode('utf-8') + old_key = key.decode("utf-8") # old: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} value = self.redis.get(old_key) value = json.loads(value) - chat_id = old_key[len(prefix):] + chat_id = old_key[len(prefix) :] user_id = list(value.keys())[0] - state = value[user_id]['state'] - state_data = value[user_id]['data'] + state = value[user_id]["state"] + state_data = value[user_id]["data"] # set new format - new_key = self._get_key(int(chat_id), int(user_id), self.prefix, self.separator, bot_id=bot_id) + new_key = self._get_key( + int(chat_id), int(user_id), self.prefix, self.separator, bot_id=bot_id + ) self.redis.hset(new_key, "state", state) self.redis.hset(new_key, "data", json.dumps(state_data)) From dbfa514fc389d527ed368cf4630e40b957d88d6e Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 27 Jul 2024 15:12:27 +0500 Subject: [PATCH 316/480] code cleanuop & renamed aio -> asyncio --- .../asynchronous_telebot/custom_states.py | 98 +++++++++++++------ examples/custom_states.py | 91 ++++++++++++----- telebot/states/{aio => asyncio}/__init__.py | 0 telebot/states/{aio => asyncio}/context.py | 0 telebot/states/{aio => asyncio}/middleware.py | 0 5 files changed, 136 insertions(+), 53 deletions(-) rename telebot/states/{aio => asyncio}/__init__.py (100%) rename telebot/states/{aio => asyncio}/context.py (100%) rename telebot/states/{aio => asyncio}/middleware.py (100%) diff --git a/examples/asynchronous_telebot/custom_states.py b/examples/asynchronous_telebot/custom_states.py index eefc6ebbb..f0111e27e 100644 --- a/examples/asynchronous_telebot/custom_states.py +++ b/examples/asynchronous_telebot/custom_states.py @@ -1,13 +1,13 @@ -from telebot import async_telebot -from telebot import asyncio_filters, types -from telebot.states import State, StatesGroup -from telebot.states.aio.context import StateContext +from telebot import async_telebot, asyncio_filters, types from telebot.asyncio_storage import StateMemoryStorage +from telebot.states import State, StatesGroup +from telebot.states.asyncio.context import StateContext # Initialize the bot state_storage = StateMemoryStorage() # don't use this in production; switch to redis bot = async_telebot.AsyncTeleBot("TOKEN", state_storage=state_storage) + # Define states class MyStates(StatesGroup): name = State() @@ -15,25 +15,39 @@ class MyStates(StatesGroup): color = State() hobby = State() + # Start command handler -@bot.message_handler(commands=['start']) +@bot.message_handler(commands=["start"]) async def start_ex(message: types.Message, state: StateContext): await state.set(MyStates.name) - await bot.send_message(message.chat.id, 'Hello! What is your first name?', reply_to_message_id=message.message_id) + await bot.send_message( + message.chat.id, + "Hello! What is your first name?", + reply_to_message_id=message.message_id, + ) + # Cancel command handler -@bot.message_handler(state="*", commands=['cancel']) +@bot.message_handler(state="*", commands=["cancel"]) async def any_state(message: types.Message, state: StateContext): await state.delete() - await bot.send_message(message.chat.id, 'Your information has been cleared. Type /start to begin again.', reply_to_message_id=message.message_id) + await bot.send_message( + message.chat.id, + "Your information has been cleared. Type /start to begin again.", + reply_to_message_id=message.message_id, + ) + # Handler for name input @bot.message_handler(state=MyStates.name) async def name_get(message: types.Message, state: StateContext): await state.set(MyStates.age) - await bot.send_message(message.chat.id, "How old are you?", reply_to_message_id=message.message_id) + await bot.send_message( + message.chat.id, "How old are you?", reply_to_message_id=message.message_id + ) await state.add_data(name=message.text) + # Handler for age input @bot.message_handler(state=MyStates.age, is_digit=True) async def ask_color(message: types.Message, state: StateContext): @@ -46,7 +60,13 @@ async def ask_color(message: types.Message, state: StateContext): buttons = [types.KeyboardButton(color) for color in colors] keyboard.add(*buttons) - await bot.send_message(message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + await bot.send_message( + message.chat.id, + "What is your favorite color? Choose from the options below.", + reply_markup=keyboard, + reply_to_message_id=message.message_id, + ) + # Handler for color input @bot.message_handler(state=MyStates.color) @@ -60,15 +80,23 @@ async def ask_hobby(message: types.Message, state: StateContext): buttons = [types.KeyboardButton(hobby) for hobby in hobbies] keyboard.add(*buttons) - await bot.send_message(message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + await bot.send_message( + message.chat.id, + "What is one of your hobbies? Choose from the options below.", + reply_markup=keyboard, + reply_to_message_id=message.message_id, + ) + # Handler for hobby input; use filters to ease validation -@bot.message_handler(state=MyStates.hobby, text=['Reading', 'Traveling', 'Gaming', 'Cooking']) +@bot.message_handler( + state=MyStates.hobby, text=["Reading", "Traveling", "Gaming", "Cooking"] +) async def finish(message: types.Message, state: StateContext): async with state.data() as data: - name = data.get('name') - age = data.get('age') - color = data.get('color') + name = data.get("name") + age = data.get("age") + color = data.get("color") hobby = message.text # Get the hobby from the message text # Provide a fun fact based on color @@ -79,24 +107,36 @@ async def finish(message: types.Message, state: StateContext): "Yellow": "Yellow is a cheerful color often associated with happiness.", "Purple": "Purple signifies royalty and luxury.", "Orange": "Orange is a vibrant color that stimulates enthusiasm.", - "Other": "Colors have various meanings depending on context." + "Other": "Colors have various meanings depending on context.", } - color_fact = color_facts.get(color, "Colors have diverse meanings, and yours is unique!") - - msg = (f"Thank you for sharing! Here is a summary of your information:\n" - f"First Name: {name}\n" - f"Age: {age}\n" - f"Favorite Color: {color}\n" - f"Fun Fact about your color: {color_fact}\n" - f"Favorite Hobby: {hobby}") - - await bot.send_message(message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id) + color_fact = color_facts.get( + color, "Colors have diverse meanings, and yours is unique!" + ) + + msg = ( + f"Thank you for sharing! Here is a summary of your information:\n" + f"First Name: {name}\n" + f"Age: {age}\n" + f"Favorite Color: {color}\n" + f"Fun Fact about your color: {color_fact}\n" + f"Favorite Hobby: {hobby}" + ) + + await bot.send_message( + message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id + ) await state.delete() + # Handler for incorrect age input @bot.message_handler(state=MyStates.age, is_digit=False) async def age_incorrect(message: types.Message): - await bot.send_message(message.chat.id, 'Please enter a valid number for age.', reply_to_message_id=message.message_id) + await bot.send_message( + message.chat.id, + "Please enter a valid number for age.", + reply_to_message_id=message.message_id, + ) + # Add custom filters bot.add_custom_filter(asyncio_filters.StateFilter(bot)) @@ -104,9 +144,11 @@ async def age_incorrect(message: types.Message): bot.add_custom_filter(asyncio_filters.TextMatchFilter()) # necessary for state parameter in handlers. -from telebot.states.aio.middleware import StateMiddleware +from telebot.states.asyncio.middleware import StateMiddleware + bot.setup_middleware(StateMiddleware(bot)) # Start polling import asyncio + asyncio.run(bot.polling()) diff --git a/examples/custom_states.py b/examples/custom_states.py index a488664b2..131dd1d42 100644 --- a/examples/custom_states.py +++ b/examples/custom_states.py @@ -6,8 +6,8 @@ # Initialize the bot state_storage = StateMemoryStorage() # don't use this in production; switch to redis -bot = telebot.TeleBot("TOKEN", state_storage=state_storage, - use_class_middlewares=True) +bot = telebot.TeleBot("TOKEN", state_storage=state_storage, use_class_middlewares=True) + # Define states class MyStates(StatesGroup): @@ -16,25 +16,39 @@ class MyStates(StatesGroup): color = State() hobby = State() + # Start command handler -@bot.message_handler(commands=['start']) +@bot.message_handler(commands=["start"]) def start_ex(message: types.Message, state: StateContext): state.set(MyStates.name) - bot.send_message(message.chat.id, 'Hello! What is your first name?', reply_to_message_id=message.message_id) + bot.send_message( + message.chat.id, + "Hello! What is your first name?", + reply_to_message_id=message.message_id, + ) + # Cancel command handler -@bot.message_handler(state="*", commands=['cancel']) +@bot.message_handler(state="*", commands=["cancel"]) def any_state(message: types.Message, state: StateContext): state.delete() - bot.send_message(message.chat.id, 'Your information has been cleared. Type /start to begin again.', reply_to_message_id=message.message_id) + bot.send_message( + message.chat.id, + "Your information has been cleared. Type /start to begin again.", + reply_to_message_id=message.message_id, + ) + # Handler for name input @bot.message_handler(state=MyStates.name) def name_get(message: types.Message, state: StateContext): state.set(MyStates.age) - bot.send_message(message.chat.id, "How old are you?", reply_to_message_id=message.message_id) + bot.send_message( + message.chat.id, "How old are you?", reply_to_message_id=message.message_id + ) state.add_data(name=message.text) + # Handler for age input @bot.message_handler(state=MyStates.age, is_digit=True) def ask_color(message: types.Message, state: StateContext): @@ -47,7 +61,13 @@ def ask_color(message: types.Message, state: StateContext): buttons = [types.KeyboardButton(color) for color in colors] keyboard.add(*buttons) - bot.send_message(message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + bot.send_message( + message.chat.id, + "What is your favorite color? Choose from the options below.", + reply_markup=keyboard, + reply_to_message_id=message.message_id, + ) + # Handler for color input @bot.message_handler(state=MyStates.color) @@ -61,15 +81,23 @@ def ask_hobby(message: types.Message, state: StateContext): buttons = [types.KeyboardButton(hobby) for hobby in hobbies] keyboard.add(*buttons) - bot.send_message(message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, reply_to_message_id=message.message_id) + bot.send_message( + message.chat.id, + "What is one of your hobbies? Choose from the options below.", + reply_markup=keyboard, + reply_to_message_id=message.message_id, + ) + # Handler for hobby input -@bot.message_handler(state=MyStates.hobby, text=['Reading', 'Traveling', 'Gaming', 'Cooking']) +@bot.message_handler( + state=MyStates.hobby, text=["Reading", "Traveling", "Gaming", "Cooking"] +) def finish(message: types.Message, state: StateContext): with state.data() as data: - name = data.get('name') - age = data.get('age') - color = data.get('color') + name = data.get("name") + age = data.get("age") + color = data.get("color") hobby = message.text # Get the hobby from the message text # Provide a fun fact based on color @@ -80,24 +108,36 @@ def finish(message: types.Message, state: StateContext): "Yellow": "Yellow is a cheerful color often associated with happiness.", "Purple": "Purple signifies royalty and luxury.", "Orange": "Orange is a vibrant color that stimulates enthusiasm.", - "Other": "Colors have various meanings depending on context." + "Other": "Colors have various meanings depending on context.", } - color_fact = color_facts.get(color, "Colors have diverse meanings, and yours is unique!") - - msg = (f"Thank you for sharing! Here is a summary of your information:\n" - f"First Name: {name}\n" - f"Age: {age}\n" - f"Favorite Color: {color}\n" - f"Fun Fact about your color: {color_fact}\n" - f"Favorite Hobby: {hobby}") - - bot.send_message(message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id) + color_fact = color_facts.get( + color, "Colors have diverse meanings, and yours is unique!" + ) + + msg = ( + f"Thank you for sharing! Here is a summary of your information:\n" + f"First Name: {name}\n" + f"Age: {age}\n" + f"Favorite Color: {color}\n" + f"Fun Fact about your color: {color_fact}\n" + f"Favorite Hobby: {hobby}" + ) + + bot.send_message( + message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id + ) state.delete() + # Handler for incorrect age input @bot.message_handler(state=MyStates.age, is_digit=False) def age_incorrect(message: types.Message): - bot.send_message(message.chat.id, 'Please enter a valid number for age.', reply_to_message_id=message.message_id) + bot.send_message( + message.chat.id, + "Please enter a valid number for age.", + reply_to_message_id=message.message_id, + ) + # Add custom filters bot.add_custom_filter(custom_filters.StateFilter(bot)) @@ -106,6 +146,7 @@ def age_incorrect(message: types.Message): # necessary for state parameter in handlers. from telebot.states.sync.middleware import StateMiddleware + bot.setup_middleware(StateMiddleware(bot)) # Start polling diff --git a/telebot/states/aio/__init__.py b/telebot/states/asyncio/__init__.py similarity index 100% rename from telebot/states/aio/__init__.py rename to telebot/states/asyncio/__init__.py diff --git a/telebot/states/aio/context.py b/telebot/states/asyncio/context.py similarity index 100% rename from telebot/states/aio/context.py rename to telebot/states/asyncio/context.py diff --git a/telebot/states/aio/middleware.py b/telebot/states/asyncio/middleware.py similarity index 100% rename from telebot/states/aio/middleware.py rename to telebot/states/asyncio/middleware.py From 303d11adf8d9c24e27239cbcd72fd1665a4c362b Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 27 Jul 2024 18:52:00 +0500 Subject: [PATCH 317/480] Improved typehints for types.py --- telebot/types.py | 1243 ++++++++++++++++++++++++---------------------- 1 file changed, 656 insertions(+), 587 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 6913452be..7cb7070a9 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -5,7 +5,7 @@ import logging import os from pathlib import Path -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional, Union, Any, Tuple from abc import ABC try: @@ -26,7 +26,6 @@ class JsonSerializable(object): """ Subclasses of this class are guaranteed to be able to be converted to JSON format. All subclasses of this class must override to_json. - """ def to_json(self): @@ -45,7 +44,6 @@ class Dictionaryable(object): """ Subclasses of this class are guaranteed to be able to be converted to dictionary. All subclasses of this class must override to_dict. - """ def to_dict(self): @@ -236,29 +234,29 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, business_connection, business_message, edited_business_message, deleted_business_messages, **kwargs): - self.update_id = update_id - self.message = message - self.edited_message = edited_message - self.channel_post = channel_post - self.edited_channel_post = edited_channel_post - self.inline_query = inline_query - self.chosen_inline_result = chosen_inline_result - self.callback_query = callback_query - self.shipping_query = shipping_query - self.pre_checkout_query = pre_checkout_query - self.poll = poll - self.poll_answer = poll_answer - self.my_chat_member = my_chat_member - self.chat_member = chat_member - self.chat_join_request = chat_join_request - self.message_reaction = message_reaction - self.message_reaction_count = message_reaction_count - self.removed_chat_boost = removed_chat_boost - self.chat_boost = chat_boost - self.business_connection = business_connection - self.business_message = business_message - self.edited_business_message = edited_business_message - self.deleted_business_messages = deleted_business_messages + self.update_id: int = update_id + self.message: Optional[Message] = message + self.edited_message: Optional[Message] = edited_message + self.channel_post: Optional[Message] = channel_post + self.edited_channel_post: Optional[Message] = edited_channel_post + self.inline_query: Optional[InlineQuery] = inline_query + self.chosen_inline_result: Optional[ChosenInlineResult] = chosen_inline_result + self.callback_query: Optional[CallbackQuery] = callback_query + self.shipping_query: Optional[ShippingQuery] = shipping_query + self.pre_checkout_query: Optional[PreCheckoutQuery] = pre_checkout_query + self.poll: Optional[Poll] = poll + self.poll_answer: Optional[PollAnswer] = poll_answer + self.my_chat_member: Optional[ChatMemberUpdated] = my_chat_member + self.chat_member: Optional[ChatMemberUpdated] = chat_member + self.chat_join_request: Optional[ChatJoinRequest] = chat_join_request + self.message_reaction: Optional[MessageReactionUpdated] = message_reaction + self.message_reaction_count: Optional[MessageReactionCountUpdated] = message_reaction_count + self.removed_chat_boost: Optional[ChatBoostRemoved] = removed_chat_boost + self.chat_boost: Optional[ChatBoostUpdated] = chat_boost + self.business_connection: Optional[BusinessConnection] = business_connection + self.business_message: Optional[Message] = business_message + self.edited_business_message: Optional[Message] = edited_business_message + self.deleted_business_messages: Optional[BusinessMessagesDeleted] = deleted_business_messages @@ -384,8 +382,8 @@ def __init__(self, chat, from_user, user_chat_id, date, bio=None, invite_link=No self.chat: Chat = chat self.from_user: User = from_user self.date: str = date - self.bio: str = bio - self.invite_link: ChatInviteLink = invite_link + self.bio: Optional[str] = bio + self.invite_link: Optional[ChatInviteLink] = invite_link self.user_chat_id: int = user_chat_id class WebhookInfo(JsonDeserializable): @@ -438,15 +436,15 @@ def de_json(cls, json_string): def __init__(self, url, has_custom_certificate, pending_update_count, ip_address=None, last_error_date=None, last_error_message=None, last_synchronization_error_date=None, max_connections=None, allowed_updates=None, **kwargs): - self.url = url - self.has_custom_certificate = has_custom_certificate - self.pending_update_count = pending_update_count - self.ip_address = ip_address - self.last_error_date = last_error_date - self.last_error_message = last_error_message - self.last_synchronization_error_date = last_synchronization_error_date - self.max_connections = max_connections - self.allowed_updates = allowed_updates + self.url: str = url + self.has_custom_certificate: bool = has_custom_certificate + self.pending_update_count: int = pending_update_count + self.ip_address: Optional[str] = ip_address + self.last_error_date: Optional[int] = last_error_date + self.last_error_message: Optional[str] = last_error_message + self.last_synchronization_error_date: Optional[int] = last_synchronization_error_date + self.max_connections: Optional[int] = max_connections + self.allowed_updates: Optional[int] = allowed_updates class User(JsonDeserializable, Dictionaryable, JsonSerializable): @@ -510,18 +508,18 @@ def __init__(self, id, is_bot, first_name, last_name=None, username=None, langua self.id: int = id self.is_bot: bool = is_bot self.first_name: str = first_name - self.username: str = username - self.last_name: str = last_name - self.language_code: str = language_code - self.can_join_groups: bool = can_join_groups - self.can_read_all_group_messages: bool = can_read_all_group_messages - self.supports_inline_queries: bool = supports_inline_queries - self.is_premium: bool = is_premium - self.added_to_attachment_menu: bool = added_to_attachment_menu - self.can_connect_to_business: bool = can_connect_to_business + self.username: Optional[str] = username + self.last_name: Optional[str] = last_name + self.language_code: Optional[str] = language_code + self.can_join_groups: Optional[bool] = can_join_groups + self.can_read_all_group_messages: Optional[bool] = can_read_all_group_messages + self.supports_inline_queries: Optional[bool] = supports_inline_queries + self.is_premium: Optional[bool] = is_premium + self.added_to_attachment_menu: Optional[bool] = added_to_attachment_menu + self.can_connect_to_business: Optional[bool] = can_connect_to_business @property - def full_name(self): + def full_name(self) -> str: """ :return: User's full name """ @@ -756,48 +754,48 @@ def __init__(self, id, type, title=None, username=None, first_name=None, can_send_paid_media=None, **kwargs): self.id: int = id self.type: str = type - self.title: str = title - self.username: str = username - self.first_name: str = first_name - self.last_name: str = last_name - self.is_forum: bool = is_forum - self.max_reaction_count: int = max_reaction_count - self.photo: ChatPhoto = photo - self.bio: str = bio - self.join_to_send_messages: bool = join_to_send_messages - self.join_by_request: bool = join_by_request - self.has_private_forwards: bool = has_private_forwards - self.has_restricted_voice_and_video_messages: bool = has_restricted_voice_and_video_messages - self.description: str = description - self.invite_link: str = invite_link - self.pinned_message: Message = pinned_message - self.permissions: ChatPermissions = permissions - self.slow_mode_delay: int = slow_mode_delay - self.message_auto_delete_time: int = message_auto_delete_time - self.has_protected_content: bool = has_protected_content - self.sticker_set_name: str = sticker_set_name - self.can_set_sticker_set: bool = can_set_sticker_set - self.linked_chat_id: int = linked_chat_id - self.location: ChatLocation = location - self.active_usernames: List[str] = active_usernames - self.emoji_status_custom_emoji_id: str = emoji_status_custom_emoji_id - self.has_hidden_members: bool = has_hidden_members - self.has_aggressive_anti_spam_enabled: bool = has_aggressive_anti_spam_enabled - self.emoji_status_expiration_date: int = emoji_status_expiration_date - self.available_reactions: List[ReactionType] = available_reactions - self.accent_color_id: int = accent_color_id - self.background_custom_emoji_id: str = background_custom_emoji_id - self.profile_accent_color_id: int = profile_accent_color_id - self.profile_background_custom_emoji_id: str = profile_background_custom_emoji_id - self.has_visible_history: bool = has_visible_history - self.unrestrict_boost_count: int = unrestrict_boost_count - self.custom_emoji_sticker_set_name: str = custom_emoji_sticker_set_name - self.business_intro: BusinessIntro = business_intro - self.business_location: BusinessLocation = business_location - self.business_opening_hours: BusinessOpeningHours = business_opening_hours - self.personal_chat: Chat = personal_chat - self.birthdate: Birthdate = birthdate - self.can_send_paid_media: bool = can_send_paid_media + self.title: Optional[str] = title + self.username: Optional[str] = username + self.first_name: Optional[str] = first_name + self.last_name: Optional[str] = last_name + self.is_forum: Optional[bool] = is_forum + self.max_reaction_count: Optional[int] = max_reaction_count + self.photo: Optional[ChatPhoto] = photo + self.bio: Optional[str] = bio + self.join_to_send_messages: Optional[bool] = join_to_send_messages + self.join_by_request: Optional[bool] = join_by_request + self.has_private_forwards: Optional[bool] = has_private_forwards + self.has_restricted_voice_and_video_messages: Optional[bool] = has_restricted_voice_and_video_messages + self.description: Optional[str] = description + self.invite_link: Optional[str] = invite_link + self.pinned_message: Optional[Message] = pinned_message + self.permissions: Optional[ChatPermissions] = permissions + self.slow_mode_delay: Optional[int] = slow_mode_delay + self.message_auto_delete_time: Optional[int] = message_auto_delete_time + self.has_protected_content: Optional[bool] = has_protected_content + self.sticker_set_name: Optional[str] = sticker_set_name + self.can_set_sticker_set: Optional[bool] = can_set_sticker_set + self.linked_chat_id: Optional[int] = linked_chat_id + self.location: Optional[ChatLocation] = location + self.active_usernames: Optional[List[str]] = active_usernames + self.emoji_status_custom_emoji_id: Optional[str] = emoji_status_custom_emoji_id + self.has_hidden_members: Optional[bool] = has_hidden_members + self.has_aggressive_anti_spam_enabled: Optional[bool] = has_aggressive_anti_spam_enabled + self.emoji_status_expiration_date: Optional[int] = emoji_status_expiration_date + self.available_reactions: Optional[List[ReactionType]] = available_reactions + self.accent_color_id: Optional[int] = accent_color_id + self.background_custom_emoji_id: Optional[str] = background_custom_emoji_id + self.profile_accent_color_id: Optional[int] = profile_accent_color_id + self.profile_background_custom_emoji_id: Optional[str] = profile_background_custom_emoji_id + self.has_visible_history: Optional[bool] = has_visible_history + self.unrestrict_boost_count: Optional[int] = unrestrict_boost_count + self.custom_emoji_sticker_set_name: Optional[str] = custom_emoji_sticker_set_name + self.business_intro: Optional[BusinessIntro] = business_intro + self.business_location: Optional[BusinessLocation] = business_location + self.business_opening_hours: Optional[BusinessOpeningHours] = business_opening_hours + self.personal_chat: Optional[Chat] = personal_chat + self.birthdate: Optional[Birthdate] = birthdate + self.can_send_paid_media: Optional[bool] = can_send_paid_media class Chat(ChatFullInfo): @@ -831,7 +829,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, message_id, **kwargs): - self.message_id = message_id + self.message_id: int = message_id class WebAppData(JsonDeserializable, Dictionaryable): @@ -858,8 +856,8 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, data, button_text, **kwargs): - self.data = data - self.button_text = button_text + self.data: str = data + self.button_text: str = button_text def to_dict(self): return {'data': self.data, 'button_text': self.button_text} @@ -1400,7 +1398,7 @@ def de_json(cls, json_string): return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod - def parse_chat(cls, chat): + def parse_chat(cls, chat) -> Union[User, GroupChat]: """ Parses chat. """ @@ -1410,7 +1408,7 @@ def parse_chat(cls, chat): return User.de_json(chat) @classmethod - def parse_photo(cls, photo_size_array): + def parse_photo(cls, photo_size_array) -> List[PhotoSize]: """ Parses photo array. """ @@ -1420,7 +1418,7 @@ def parse_photo(cls, photo_size_array): return ret @classmethod - def parse_entities(cls, message_entity_array): + def parse_entities(cls, message_entity_array) -> List[MessageEntity]: """ Parses message entity array. """ @@ -1433,7 +1431,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.content_type: str = content_type self.id: int = message_id # Lets fix the telegram usability ####up with ID in Message :) self.message_id: int = message_id - self.from_user: User = from_user + self.from_user: Optional[User] = from_user self.date: int = date self.chat: Chat = chat self.sender_chat: Optional[Chat] = None @@ -1507,20 +1505,28 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.show_caption_above_media: Optional[bool] = None self.paid_media : Optional[PaidMediaInfo] = None self.refunded_payment : Optional[RefundedPayment] = None + self.proximity_alert_triggered: Optional[ProximityAlertTriggered] = None + self.video_chat_scheduled: Optional[VideoChatScheduled] = None + self.video_chat_started: Optional[VideoChatStarted] = None + self.video_chat_ended: Optional[VideoChatEnded] = None + self.video_chat_participants_invited: Optional[VideoChatParticipantsInvited] = None + self.web_app_data: Optional[WebAppData] = None + self.message_auto_delete_timer_changed: Optional[MessageAutoDeleteTimerChanged] = None + for key in options: setattr(self, key, options[key]) self.json = json_string @property - def html_text(self): + def html_text(self) -> str: """ Returns html-rendered text. """ return apply_html_entities(self.text, self.entities, getattr(self, "custom_subs", None)) @property - def html_caption(self): + def html_caption(self) -> str: """ Returns html-rendered caption. """ @@ -1529,25 +1535,21 @@ def html_caption(self): @property def voice_chat_scheduled(self): logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') - # noinspection PyUnresolvedReferences return self.video_chat_scheduled @property def voice_chat_started(self): logger.warning('The parameter "voice_chat_started" is deprecated, use "video_chat_started" instead') - # noinspection PyUnresolvedReferences return self.video_chat_started @property def voice_chat_ended(self): logger.warning('The parameter "voice_chat_ended" is deprecated, use "video_chat_ended" instead') - # noinspection PyUnresolvedReferences return self.video_chat_ended @property def voice_chat_participants_invited(self): logger.warning('The parameter "voice_chat_participants_invited" is deprecated, use "video_chat_participants_invited" instead') - # noinspection PyUnresolvedReferences return self.video_chat_participants_invited @property @@ -1671,7 +1673,7 @@ def __init__(self, type, offset, length, url=None, user=None, language=None, cus self.url: str = url self.user: User = user self.language: str = language - self.custom_emoji_id: str = custom_emoji_id + self.custom_emoji_id: Optional[str] = custom_emoji_id def to_json(self): return json.dumps(self.to_dict()) @@ -1755,7 +1757,7 @@ def __init__(self, file_id, file_unique_id, width, height, file_size=None, **kwa self.file_unique_id: str = file_unique_id self.width: int = width self.height: int = height - self.file_size: int = file_size + self.file_size: Optional[int] = file_size class Audio(JsonDeserializable): @@ -1812,15 +1814,15 @@ def __init__(self, file_id, file_unique_id, duration, performer=None, title=None self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.duration: int = duration - self.performer: str = performer - self.title: str = title - self.file_name: str = file_name - self.mime_type: str = mime_type - self.file_size: int = file_size - self.thumbnail: PhotoSize = thumbnail + self.performer: Optional[str] = performer + self.title: Optional[str] = title + self.file_name: Optional[str] = file_name + self.mime_type: Optional[str] = mime_type + self.file_size: Optional[int] = file_size + self.thumbnail: Optional[PhotoSize] = thumbnail @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -1862,8 +1864,8 @@ def __init__(self, file_id, file_unique_id, duration, mime_type=None, file_size= self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.duration: int = duration - self.mime_type: str = mime_type - self.file_size: int = file_size + self.mime_type: Optional[str] = mime_type + self.file_size: Optional[int] = file_size class Document(JsonDeserializable): @@ -1909,13 +1911,13 @@ def de_json(cls, json_string): def __init__(self, file_id, file_unique_id, thumbnail=None, file_name=None, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id - self.thumbnail: PhotoSize = thumbnail - self.file_name: str = file_name - self.mime_type: str = mime_type - self.file_size: int = file_size + self.thumbnail: Optional[PhotoSize] = thumbnail + self.file_name: Optional[str] = file_name + self.mime_type: Optional[str] = mime_type + self.file_size: Optional[int] = file_size @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -1974,12 +1976,12 @@ def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=N self.height: int = height self.duration: int = duration self.thumbnail: PhotoSize = thumbnail - self.file_name: str = file_name - self.mime_type: str = mime_type - self.file_size: int = file_size + self.file_name: Optional[str] = file_name + self.mime_type: Optional[str] = mime_type + self.file_size: Optional[int] = file_size @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -2025,11 +2027,11 @@ def __init__(self, file_id, file_unique_id, length, duration, thumbnail=None, fi self.file_unique_id: str = file_unique_id self.length: int = length self.duration: int = duration - self.thumbnail: PhotoSize = thumbnail - self.file_size: int = file_size + self.thumbnail: Optional[PhotoSize] = thumbnail + self.file_size: Optional[int] = file_size @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -2069,9 +2071,9 @@ def de_json(cls, json_string): def __init__(self, phone_number, first_name, last_name=None, user_id=None, vcard=None, **kwargs): self.phone_number: str = phone_number self.first_name: str = first_name - self.last_name: str = last_name - self.user_id: int = user_id - self.vcard: str = vcard + self.last_name: Optional[str] = last_name + self.user_id: Optional[int] = user_id + self.vcard: Optional[str] = vcard class Location(JsonDeserializable, JsonSerializable, Dictionaryable): @@ -2113,10 +2115,10 @@ def __init__(self, longitude, latitude, horizontal_accuracy=None, live_period=None, heading=None, proximity_alert_radius=None, **kwargs): self.longitude: float = longitude self.latitude: float = latitude - self.horizontal_accuracy: float = horizontal_accuracy - self.live_period: int = live_period - self.heading: int = heading - self.proximity_alert_radius: int = proximity_alert_radius + self.horizontal_accuracy: Optional[float] = horizontal_accuracy + self.live_period: Optional[int] = live_period + self.heading: Optional[int] = heading + self.proximity_alert_radius: Optional[int] = proximity_alert_radius def to_json(self): return json.dumps(self.to_dict()) @@ -2175,10 +2177,10 @@ def __init__(self, location, title, address, foursquare_id=None, foursquare_type self.location: Location = location self.title: str = title self.address: str = address - self.foursquare_id: str = foursquare_id - self.foursquare_type: str = foursquare_type - self.google_place_id: str = google_place_id - self.google_place_type: str = google_place_type + self.foursquare_id: Optional[str] = foursquare_id + self.foursquare_type: Optional[str] = foursquare_type + self.google_place_id: Optional[str] = google_place_id + self.google_place_type: Optional[str] = google_place_type class UserProfilePhotos(JsonDeserializable): @@ -2244,8 +2246,8 @@ def de_json(cls, json_string): def __init__(self, file_id, file_unique_id, file_size=None, file_path=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id - self.file_size: int = file_size - self.file_path: str = file_path + self.file_size: Optional[int] = file_size + self.file_path: Optional[str] = file_path # noinspection PyUnresolvedReferences @@ -2272,8 +2274,8 @@ class ForceReply(JsonSerializable): :rtype: :class:`telebot.types.ForceReply` """ def __init__(self, selective: Optional[bool]=None, input_field_placeholder: Optional[str]=None): - self.selective: bool = selective - self.input_field_placeholder: str = input_field_placeholder + self.selective: Optional[bool] = selective + self.input_field_placeholder: Optional[str] = input_field_placeholder def to_json(self): json_dict = {'force_reply': True} @@ -2307,8 +2309,8 @@ class ReplyKeyboardRemove(JsonSerializable): :return: Instance of the class :rtype: :class:`telebot.types.ReplyKeyboardRemove` """ - def __init__(self, selective=None): - self.selective: bool = selective + def __init__(self, selective: Optional[bool]=None): + self.selective: Optional[bool] = selective def to_json(self): json_dict = {'remove_keyboard': True} @@ -2408,15 +2410,15 @@ def __init__(self, resize_keyboard: Optional[bool]=None, one_time_keyboard: Opti logger.error('Telegram does not support reply keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys - self.resize_keyboard: bool = resize_keyboard - self.one_time_keyboard: bool = one_time_keyboard - self.selective: bool = selective - self.row_width: int = row_width - self.input_field_placeholder: str = input_field_placeholder + self.resize_keyboard: Optional[bool] = resize_keyboard + self.one_time_keyboard: Optional[bool] = one_time_keyboard + self.selective: Optional[bool] = selective + self.row_width: Optional[int] = row_width + self.input_field_placeholder: Optional[str] = input_field_placeholder self.keyboard: List[List[KeyboardButton]] = [] - self.is_persistent: bool = is_persistent + self.is_persistent: Optional[bool] = is_persistent - def add(self, *args, row_width=None): + def add(self, *args, row_width=None) -> 'ReplyKeyboardMarkup': """ This function adds strings to the keyboard, while not exceeding row_width. E.g. ReplyKeyboardMarkup#add("A", "B", "C") yields the json result {keyboard: [["A"], ["B"], ["C"]]} @@ -2455,7 +2457,7 @@ def add(self, *args, row_width=None): return self - def row(self, *args): + def row(self, *args) -> 'ReplyKeyboardMarkup': """ Adds a list of KeyboardButton to the keyboard. This function does not consider row_width. ReplyKeyboardMarkup#row("A")#row("B", "C")#to_json() outputs '{keyboard: [["A"], ["B", "C"]]}' @@ -2713,12 +2715,12 @@ def __init__(self, text: str, request_contact: Optional[bool]=None, web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUser]=None, request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None): self.text: str = text - self.request_contact: bool = request_contact - self.request_location: bool = request_location - self.request_poll: KeyboardButtonPollType = request_poll - self.web_app: WebAppInfo = web_app - self.request_chat: KeyboardButtonRequestChat = request_chat - self.request_users: KeyboardButtonRequestUsers = request_users + self.request_contact: Optional[bool] = request_contact + self.request_location: Optional[bool] = request_location + self.request_poll: Optional[KeyboardButtonPollType] = request_poll + self.web_app: Optional[WebAppInfo] = web_app + self.request_chat: Optional[KeyboardButtonRequestChat] = request_chat + self.request_users: Optional[KeyboardButtonRequestUsers] = request_users if request_user is not None: logger.warning('The parameter "request_user" is deprecated, use "request_users" instead') if self.request_users is None: @@ -2795,7 +2797,7 @@ def __init__(self, keyboard=None, row_width=3): self.row_width: int = row_width self.keyboard: List[List[InlineKeyboardButton]] = keyboard or [] - def add(self, *args, row_width=None): + def add(self, *args, row_width=None) -> 'InlineKeyboardMarkup': """ This method adds buttons to the keyboard without exceeding row_width. @@ -2829,7 +2831,7 @@ def add(self, *args, row_width=None): return self - def row(self, *args): + def row(self, *args) -> 'InlineKeyboardMarkup': """ Adds a list of InlineKeyboardButton to the keyboard. This method does not consider row_width. @@ -2922,18 +2924,20 @@ def de_json(cls, json_string): return cls(**obj) - def __init__(self, text, url=None, callback_data=None, web_app=None, switch_inline_query=None, - switch_inline_query_current_chat=None, switch_inline_query_chosen_chat=None, callback_game=None, pay=None, login_url=None, **kwargs): + def __init__(self, text: str, url: Optional[str]=None, callback_data: Optional[str]=None, web_app: Optional[WebAppInfo]=None, + switch_inline_query: Optional[str]=None, switch_inline_query_current_chat: Optional[str]=None, + switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat]=None, callback_game=None, pay: Optional[bool]=None, + login_url: Optional[LoginUrl]=None, **kwargs): self.text: str = text - self.url: str = url - self.callback_data: str = callback_data - self.web_app: WebAppInfo = web_app - self.switch_inline_query: str = switch_inline_query - self.switch_inline_query_current_chat: str = switch_inline_query_current_chat - self.switch_inline_query_chosen_chat: SwitchInlineQueryChosenChat = switch_inline_query_chosen_chat + self.url: Optional[str] = url + self.callback_data: Optional[str] = callback_data + self.web_app: Optional[WebAppInfo] = web_app + self.switch_inline_query: Optional[str] = switch_inline_query + self.switch_inline_query_current_chat: Optional[str] = switch_inline_query_current_chat + self.switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = switch_inline_query_chosen_chat self.callback_game = callback_game # Not Implemented - self.pay: bool = pay - self.login_url: LoginUrl = login_url + self.pay: Optional[bool] = pay + self.login_url: Optional[LoginUrl] = login_url def to_json(self): return json.dumps(self.to_dict()) @@ -2995,11 +2999,12 @@ def de_json(cls, json_string): obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - def __init__(self, url, forward_text=None, bot_username=None, request_write_access=None, **kwargs): + def __init__(self, url: str, forward_text: Optional[str]=None, bot_username: Optional[str]=None, request_write_access: Optional[bool]=None, + **kwargs): self.url: str = url - self.forward_text: str = forward_text - self.bot_username: str = bot_username - self.request_write_access: bool = request_write_access + self.forward_text: Optional[str] = forward_text + self.bot_username: Optional[str] = bot_username + self.request_write_access: Optional[bool] = request_write_access def to_json(self): return json.dumps(self.to_dict()) @@ -3073,10 +3078,10 @@ def __init__( self.id: int = id self.from_user: User = from_user self.message: Union[Message, InaccessibleMessage] = message - self.inline_message_id: str = inline_message_id - self.chat_instance: str = chat_instance - self.data: str = data - self.game_short_name: str = game_short_name + self.inline_message_id: Optional[str] = inline_message_id + self.chat_instance: Optional[str] = chat_instance + self.data: Optional[str] = data + self.game_short_name: Optional[str] = game_short_name self.json = json_string @@ -3510,31 +3515,31 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send can_add_web_page_previews=None, can_change_info=None, can_invite_users=None, can_pin_messages=None, can_manage_topics=None, **kwargs): - self.can_send_messages: bool = can_send_messages - self.can_send_polls: bool = can_send_polls - self.can_send_other_messages: bool = can_send_other_messages - self.can_add_web_page_previews: bool = can_add_web_page_previews - self.can_change_info: bool = can_change_info - self.can_invite_users: bool = can_invite_users - self.can_pin_messages: bool = can_pin_messages - self.can_manage_topics: bool = can_manage_topics - self.can_send_audios: bool = can_send_audios - self.can_send_documents: bool = can_send_documents - self.can_send_photos: bool = can_send_photos - self.can_send_videos: bool = can_send_videos - self.can_send_video_notes: bool = can_send_video_notes - self.can_send_voice_notes: bool = can_send_voice_notes + self.can_send_messages: Optional[bool] = can_send_messages + self.can_send_polls: Optional[bool] = can_send_polls + self.can_send_other_messages: Optional[bool] = can_send_other_messages + self.can_add_web_page_previews: Optional[bool] = can_add_web_page_previews + self.can_change_info: Optional[bool] = can_change_info + self.can_invite_users: Optional[bool] = can_invite_users + self.can_pin_messages: Optional[bool] = can_pin_messages + self.can_manage_topics: Optional[bool] = can_manage_topics + self.can_send_audios: Optional[bool] = can_send_audios + self.can_send_documents: Optional[bool] = can_send_documents + self.can_send_photos: Optional[bool] = can_send_photos + self.can_send_videos: Optional[bool] = can_send_videos + self.can_send_video_notes: Optional[bool] = can_send_video_notes + self.can_send_voice_notes: Optional[bool] = can_send_voice_notes if kwargs.get("de_json", False) and can_send_media_messages is not None: # Telegram passes can_send_media_messages in Chat.permissions. Temporary created parameter "de_json" allows avoid # deprection warning and individual parameters overriding. logger.warning('The parameter "can_send_media_messages" is deprecated. Use individual parameters like "can_send_audios", "can_send_documents" etc.') - self.can_send_audios = can_send_media_messages - self.can_send_documents = can_send_media_messages - self.can_send_photos = can_send_media_messages - self.can_send_videos = can_send_media_messages - self.can_send_video_notes = can_send_media_messages - self.can_send_voice_notes = can_send_media_messages + self.can_send_audios: Optional[bool] = can_send_media_messages + self.can_send_documents: Optional[bool] = can_send_media_messages + self.can_send_photos: Optional[bool] = can_send_media_messages + self.can_send_videos: Optional[bool] = can_send_media_messages + self.can_send_video_notes: Optional[bool] = can_send_media_messages + self.can_send_voice_notes: Optional[bool] = can_send_media_messages def to_json(self): @@ -3765,7 +3770,7 @@ class BotCommandScopeChat(BotCommandScope): :return: Instance of the class :rtype: :class:`telebot.types.BotCommandScopeChat` """ - def __init__(self, chat_id=None): + def __init__(self, chat_id: Optional[Union[str, int]]=None): super(BotCommandScopeChat, self).__init__(type='chat', chat_id=chat_id) @@ -3786,7 +3791,7 @@ class BotCommandScopeChatAdministrators(BotCommandScope): :return: Instance of the class :rtype: :class:`telebot.types.BotCommandScopeChatAdministrators` """ - def __init__(self, chat_id=None): + def __init__(self, chat_id: Optional[Union[str, int]]=None): super(BotCommandScopeChatAdministrators, self).__init__(type='chat_administrators', chat_id=chat_id) @@ -3810,7 +3815,7 @@ class BotCommandScopeChatMember(BotCommandScope): :return: Instance of the class :rtype: :class:`telebot.types.BotCommandScopeChatMember` """ - def __init__(self, chat_id=None, user_id=None): + def __init__(self, chat_id: Optional[Union[str, int]]=None, user_id: Optional[Union[str, int]]=None): super(BotCommandScopeChatMember, self).__init__(type='chat_member', chat_id=chat_id, user_id=user_id) @@ -3861,8 +3866,8 @@ def __init__(self, id, from_user, query, offset, chat_type=None, location=None, self.from_user: User = from_user self.query: str = query self.offset: str = offset - self.chat_type: str = chat_type - self.location: Location = location + self.chat_type: Optional[str] = chat_type + self.location: Optional[Location] = location class InputTextMessageContent(Dictionaryable): @@ -3891,20 +3896,19 @@ class InputTextMessageContent(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.InputTextMessageContent` """ - def __init__( - self, message_text, parse_mode=None, entities=None, disable_web_page_preview=None, - link_preview_options=None): + def __init__(self, message_text: str, parse_mode: Optional[str] = None, entities: Optional[List[MessageEntity]] = None, + disable_web_page_preview: Optional[bool] = None, link_preview_options: Optional[LinkPreviewOptions] = None): self.message_text: str = message_text - self.parse_mode: str = parse_mode - self.entities: List[MessageEntity] = entities - self.link_preview_options: LinkPreviewOptions = link_preview_options + self.parse_mode: Optional[str] = parse_mode + self.entities: Optional[List[MessageEntity]] = entities + self.link_preview_options: Optional[LinkPreviewOptions] = link_preview_options if disable_web_page_preview is not None: logger.warning('The parameter "disable_web_page_preview" is deprecated. Use "link_preview_options" instead.') if link_preview_options: logger.warning('Both "link_preview_options" and "disable_web_page_preview" parameters are set: conflicting, "disable_web_page_preview" is deprecated') else: - self.link_preview_options: LinkPreviewOptions = LinkPreviewOptions(is_disabled=disable_web_page_preview) + self.link_preview_options: Optional[LinkPreviewOptions] = LinkPreviewOptions(is_disabled=disable_web_page_preview) def to_dict(self): json_dict = {'message_text': self.message_text} @@ -3947,10 +3951,10 @@ class InputLocationMessageContent(Dictionaryable): def __init__(self, latitude, longitude, horizontal_accuracy=None, live_period=None, heading=None, proximity_alert_radius=None): self.latitude: float = latitude self.longitude: float = longitude - self.horizontal_accuracy: float = horizontal_accuracy - self.live_period: int = live_period - self.heading: int = heading - self.proximity_alert_radius: int = proximity_alert_radius + self.horizontal_accuracy: Optional[float] = horizontal_accuracy + self.live_period: Optional[int] = live_period + self.heading: Optional[int] = heading + self.proximity_alert_radius: Optional[int] = proximity_alert_radius def to_dict(self): json_dict = {'latitude': self.latitude, 'longitude': self.longitude} @@ -4005,10 +4009,10 @@ def __init__(self, latitude, longitude, title, address, foursquare_id=None, four self.longitude: float = longitude self.title: str = title self.address: str = address - self.foursquare_id: str = foursquare_id - self.foursquare_type: str = foursquare_type - self.google_place_id: str = google_place_id - self.google_place_type: str = google_place_type + self.foursquare_id: Optional[str] = foursquare_id + self.foursquare_type: Optional[str] = foursquare_type + self.google_place_id: Optional[str] = google_place_id + self.google_place_type: Optional[str] = google_place_type def to_dict(self): json_dict = { @@ -4052,8 +4056,8 @@ class InputContactMessageContent(Dictionaryable): def __init__(self, phone_number, first_name, last_name=None, vcard=None): self.phone_number: str = phone_number self.first_name: str = first_name - self.last_name: str = last_name - self.vcard: str = vcard + self.last_name: Optional[str] = last_name + self.vcard: Optional[str] = vcard def to_dict(self): json_dict = {'phone_number': self.phone_number, 'first_name': self.first_name} @@ -4080,8 +4084,9 @@ class InputInvoiceMessageContent(Dictionaryable): internal processes. :type payload: :obj:`str` - :param provider_token: Payment provider token, obtained via @BotFather - :type provider_token: :obj:`str` + :param provider_token: Payment provider token, obtained via @BotFather; To create invoice in stars, + provide an empty token. + :type provider_token: :obj:`str` or :obj:`None` :param currency: Three-letter ISO 4217 currency code, see more on currencies :type currency: :obj:`str` @@ -4143,16 +4148,16 @@ class InputInvoiceMessageContent(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.InputInvoiceMessageContent` """ - def __init__(self, title, description, payload, provider_token, currency, prices, - max_tip_amount=None, suggested_tip_amounts=None, provider_data=None, - photo_url=None, photo_size=None, photo_width=None, photo_height=None, - need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, - send_phone_number_to_provider=None, send_email_to_provider=None, - is_flexible=None): + + def __init__(self, title: str, description: str, payload: str, provider_token: Optional[str], currency: str, prices: List[LabeledPrice], + max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]] = None, provider_data: Optional[str] = None, + photo_url: Optional[str] = None, photo_size: Optional[int] = None, photo_width: Optional[int] = None, photo_height: Optional[int] = None, + need_name: Optional[bool] = None, need_phone_number: Optional[bool] = None, need_email: Optional[bool] = None, need_shipping_address: Optional[bool] = None, + send_phone_number_to_provider: Optional[bool] = None, send_email_to_provider: Optional[bool] = None, is_flexible: Optional[bool] = None): self.title: str = title self.description: str = description self.payload: str = payload - self.provider_token: str = provider_token + self.provider_token: Optional[str] = provider_token self.currency: str = currency self.prices: List[LabeledPrice] = prices self.max_tip_amount: Optional[int] = max_tip_amount @@ -4209,6 +4214,7 @@ def to_dict(self): json_dict['is_flexible'] = self.is_flexible return json_dict +InputMessageContent = Union[InputTextMessageContent, InputLocationMessageContent, InputVenueMessageContent, InputContactMessageContent, InputInvoiceMessageContent] class ChosenInlineResult(JsonDeserializable): """ @@ -4247,8 +4253,8 @@ def de_json(cls, json_string): def __init__(self, result_id, from_user, query, location=None, inline_message_id=None, **kwargs): self.result_id: str = result_id self.from_user: User = from_user - self.location: Location = location - self.inline_message_id: str = inline_message_id + self.location: Optional[Location] = location + self.inline_message_id: Optional[str] = inline_message_id self.query: str = query @@ -4279,17 +4285,17 @@ class InlineQueryResultBase(ABC, Dictionaryable, JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#inlinequeryresult """ - # noinspection PyShadowingBuiltins - def __init__(self, type, id, title = None, caption = None, input_message_content = None, - reply_markup = None, caption_entities = None, parse_mode = None): - self.type = type - self.id = id - self.title = title - self.caption = caption - self.input_message_content = input_message_content - self.reply_markup = reply_markup - self.caption_entities = caption_entities - self.parse_mode = parse_mode + + def __init__(self, type: str, id: str, title: Optional[str] = None, caption: Optional[str] = None, input_message_content: Optional[InputMessageContent] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None): + self.type: str = type + self.id: str = id + self.title: Optional[str] = title + self.caption: Optional[str] = caption + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.parse_mode: Optional[str] = parse_mode def to_json(self): return json.dumps(self.to_dict()) @@ -4334,7 +4340,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, inline_message_id=None, **kwargs): - self.inline_message_id = inline_message_id + self.inline_message_id: Optional[str] = inline_message_id def to_dict(self): json_dict = {} @@ -4386,28 +4392,32 @@ class InlineQueryResultArticle(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultArticle` """ - def __init__(self, id, title, input_message_content, reply_markup=None, - url=None, hide_url=None, description=None, thumbnail_url=None, thumbnail_width=None, thumbnail_height=None): + + def __init__(self, id: str, title: str, input_message_content: InputMessageContent, reply_markup: Optional[InlineKeyboardMarkup] = None, + url: Optional[str] = None, hide_url: Optional[bool] = None, description: Optional[str] = None, + thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None): + super().__init__('article', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) - self.url = url - self.hide_url = hide_url - self.description = description - self.thumbnail_url = thumbnail_url - self.thumbnail_width = thumbnail_width - self.thumbnail_height = thumbnail_height + self.url: Optional[str] = url + self.hide_url: Optional[bool] = hide_url + self.description: Optional[str] = description + self.thumbnail_url: Optional[str] = thumbnail_url + self.thumbnail_width: Optional[int] = thumbnail_width + self.thumbnail_height: Optional[int] = thumbnail_height + @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_width(self): + def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property - def thumb_height(self): + def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height @@ -4482,21 +4492,23 @@ class InlineQueryResultPhoto(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultPhoto` """ - def __init__(self, id, photo_url, thumbnail_url, photo_width=None, photo_height=None, title=None, - description=None, caption=None, caption_entities=None, parse_mode=None, reply_markup=None, input_message_content=None, - show_caption_above_media=None): + def __init__(self, id: str, photo_url: str, thumbnail_url: str, photo_width: Optional[int] = None, photo_height: Optional[int] = None, + title: Optional[str] = None, description: Optional[str] = None, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, + show_caption_above_media: Optional[bool] = None): super().__init__('photo', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.photo_url = photo_url - self.thumbnail_url = thumbnail_url - self.photo_width = photo_width - self.photo_height = photo_height - self.description = description + self.photo_url: str = photo_url + self.thumbnail_url: str = thumbnail_url + self.photo_width: Optional[int] = photo_width + self.photo_height: Optional[int] = photo_height + self.description: Optional[str] = description self.show_caption_above_media: Optional[bool] = show_caption_above_media + @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @@ -4572,28 +4584,30 @@ class InlineQueryResultGif(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultGif` """ - def __init__(self, id, gif_url, thumbnail_url, gif_width=None, gif_height=None, - title=None, caption=None, caption_entities=None, - reply_markup=None, input_message_content=None, gif_duration=None, parse_mode=None, - thumbnail_mime_type=None, show_caption_above_media=None): + def __init__(self, id: str, gif_url: str, thumbnail_url: str, gif_width: Optional[int] = None, gif_height: Optional[int] = None, + title: Optional[str] = None, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, + gif_duration: Optional[int] = None, parse_mode: Optional[str] = None, thumbnail_mime_type: Optional[str] = None, + show_caption_above_media: Optional[bool] = None): + super().__init__('gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.gif_url = gif_url - self.gif_width = gif_width - self.gif_height = gif_height - self.thumbnail_url = thumbnail_url - self.gif_duration = gif_duration - self.thumbnail_mime_type = thumbnail_mime_type + self.gif_url: str = gif_url + self.thumbnail_url: str = thumbnail_url + self.gif_width: Optional[int] = gif_width + self.gif_height: Optional[int] = gif_height + self.gif_duration: Optional[int] = gif_duration + self.thumbnail_mime_type: Optional[str] = thumbnail_mime_type self.show_caption_above_media: Optional[bool] = show_caption_above_media @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_mime_type(self): + def thumb_mime_type(self) -> str: logger.warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') return self.thumbnail_mime_type @@ -4671,28 +4685,29 @@ class InlineQueryResultMpeg4Gif(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultMpeg4Gif` """ - def __init__(self, id, mpeg4_url, thumbnail_url, mpeg4_width=None, mpeg4_height=None, - title=None, caption=None, caption_entities=None, - parse_mode=None, reply_markup=None, input_message_content=None, mpeg4_duration=None, - thumbnail_mime_type=None, show_caption_above_media=None): + def __init__(self, id: str, mpeg4_url: str, thumbnail_url: str, mpeg4_width: Optional[int] = None, mpeg4_height: Optional[int] = None, + title: Optional[str] = None, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, + mpeg4_duration: Optional[int] = None, thumbnail_mime_type: Optional[str] = None, show_caption_above_media: Optional[bool] = None): + super().__init__('mpeg4_gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.mpeg4_url = mpeg4_url - self.mpeg4_width = mpeg4_width - self.mpeg4_height = mpeg4_height - self.thumbnail_url = thumbnail_url - self.mpeg4_duration = mpeg4_duration - self.thumbnail_mime_type = thumbnail_mime_type + self.mpeg4_url: str = mpeg4_url + self.thumbnail_url: str = thumbnail_url + self.mpeg4_width: Optional[int] = mpeg4_width + self.mpeg4_height: Optional[int] = mpeg4_height + self.mpeg4_duration: Optional[int] = mpeg4_duration + self.thumbnail_mime_type: Optional[str] = thumbnail_mime_type self.show_caption_above_media: Optional[bool] = show_caption_above_media @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_mime_type(self): + def thumb_mime_type(self) -> str: logger.warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') return self.thumbnail_mime_type @@ -4774,24 +4789,26 @@ class InlineQueryResultVideo(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultVideo` """ - def __init__(self, id, video_url, mime_type, thumbnail_url, - title, caption=None, caption_entities=None, parse_mode=None, - video_width=None, video_height=None, video_duration=None, - description=None, reply_markup=None, input_message_content=None, show_caption_above_media=None): + def __init__(self, id: str, video_url: str, mime_type: str, thumbnail_url: str, title: str, + caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, video_width: Optional[int] = None, video_height: Optional[int] = None, + video_duration: Optional[int] = None, description: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): + super().__init__('video', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.video_url = video_url - self.mime_type = mime_type - self.thumbnail_url = thumbnail_url - self.video_width = video_width - self.video_height = video_height - self.video_duration = video_duration - self.description = description + self.video_url: str = video_url + self.mime_type: str = mime_type + self.thumbnail_url: str = thumbnail_url + self.video_width: Optional[int] = video_width + self.video_height: Optional[int] = video_height + self.video_duration: Optional[int] = video_duration + self.description: Optional[str] = description self.show_caption_above_media: Optional[bool] = show_caption_above_media @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @@ -4856,15 +4873,16 @@ class InlineQueryResultAudio(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultAudio` """ - def __init__(self, id, audio_url, title, - caption=None, caption_entities=None, parse_mode=None, performer=None, - audio_duration=None, reply_markup=None, input_message_content=None): + def __init__(self, id: str, audio_url: str, title: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, performer: Optional[str] = None, audio_duration: Optional[int] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): + super().__init__('audio', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.audio_url = audio_url - self.performer = performer - self.audio_duration = audio_duration + self.audio_url: str = audio_url + self.performer: Optional[str] = performer + self.audio_duration: Optional[int] = audio_duration def to_dict(self): json_dict = super().to_dict() @@ -4918,13 +4936,15 @@ class InlineQueryResultVoice(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultVoice` """ - def __init__(self, id, voice_url, title, caption=None, caption_entities=None, - parse_mode=None, voice_duration=None, reply_markup=None, input_message_content=None): + def __init__(self, id: str, voice_url: str, title: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, voice_duration: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None): + super().__init__('voice', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.voice_url = voice_url - self.voice_duration = voice_duration + self.voice_url: str = voice_url + self.voice_duration: Optional[int] = voice_duration def to_dict(self): json_dict = super().to_dict() @@ -4988,31 +5008,34 @@ class InlineQueryResultDocument(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultDocument` """ - def __init__(self, id, title, document_url, mime_type, caption=None, caption_entities=None, - parse_mode=None, description=None, reply_markup=None, input_message_content=None, - thumbnail_url=None, thumbnail_width=None, thumbnail_height=None): + def __init__(self, id: str, title: str, document_url: str, mime_type: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, description: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None, thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, + thumbnail_height: Optional[int] = None): + super().__init__('document', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) - self.document_url = document_url - self.mime_type = mime_type - self.description = description - self.thumbnail_url = thumbnail_url - self.thumbnail_width = thumbnail_width - self.thumbnail_height = thumbnail_height + self.document_url: str = document_url + self.mime_type: str = mime_type + self.description: Optional[str] = description + self.thumbnail_url: Optional[str] = thumbnail_url + self.thumbnail_width: Optional[int] = thumbnail_width + self.thumbnail_height: Optional[int] = thumbnail_height + @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_width(self): + def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property - def thumb_height(self): + def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height @@ -5083,32 +5106,35 @@ class InlineQueryResultLocation(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultLocation` """ - def __init__(self, id, title, latitude, longitude, horizontal_accuracy, live_period=None, reply_markup=None, - input_message_content=None, thumbnail_url=None, thumbnail_width=None, thumbnail_height=None, heading=None, proximity_alert_radius = None): + def __init__(self, id: str, title: str, latitude: float, longitude: float, horizontal_accuracy: float, live_period: Optional[int] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, + thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None, + heading: Optional[int] = None, proximity_alert_radius: Optional[int] = None): + super().__init__('location', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) - self.latitude = latitude - self.longitude = longitude - self.horizontal_accuracy = horizontal_accuracy - self.live_period = live_period - self.heading: int = heading - self.proximity_alert_radius: int = proximity_alert_radius - self.thumbnail_url = thumbnail_url - self.thumbnail_width = thumbnail_width - self.thumbnail_height = thumbnail_height + self.latitude: float = latitude + self.longitude: float = longitude + self.horizontal_accuracy: float = horizontal_accuracy + self.live_period: Optional[int] = live_period + self.heading: Optional[int] = heading + self.proximity_alert_radius: Optional[int] = proximity_alert_radius + self.thumbnail_url: Optional[str] = thumbnail_url + self.thumbnail_width: Optional[int] = thumbnail_width + self.thumbnail_height: Optional[int] = thumbnail_height @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_width(self): + def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property - def thumb_height(self): + def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height @@ -5189,34 +5215,36 @@ class InlineQueryResultVenue(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultVenue` """ - def __init__(self, id, title, latitude, longitude, address, foursquare_id=None, foursquare_type=None, - reply_markup=None, input_message_content=None, thumbnail_url=None, - thumbnail_width=None, thumbnail_height=None, google_place_id=None, google_place_type=None): + def __init__(self, id: str, title: str, latitude: float, longitude: float, address: str, foursquare_id: Optional[str] = None, + foursquare_type: Optional[str] = None, google_place_id: Optional[str] = None, google_place_type: Optional[str] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, + thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None): + super().__init__('venue', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) - self.latitude = latitude - self.longitude = longitude - self.address = address - self.foursquare_id = foursquare_id - self.foursquare_type = foursquare_type - self.google_place_id = google_place_id - self.google_place_type = google_place_type - self.thumbnail_url = thumbnail_url - self.thumbnail_width = thumbnail_width - self.thumbnail_height = thumbnail_height + self.latitude: float = latitude + self.longitude: float = longitude + self.address: str = address + self.foursquare_id: Optional[str] = foursquare_id + self.foursquare_type: Optional[str] = foursquare_type + self.google_place_id: Optional[str] = google_place_id + self.google_place_type: Optional[str] = google_place_type + self.thumbnail_url: Optional[str] = thumbnail_url + self.thumbnail_width: Optional[int] = thumbnail_width + self.thumbnail_height: Optional[int] = thumbnail_height @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_width(self): + def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property - def thumb_height(self): + def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height @@ -5285,31 +5313,33 @@ class InlineQueryResultContact(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultContact` """ - def __init__(self, id, phone_number, first_name, last_name=None, vcard=None, - reply_markup=None, input_message_content=None, - thumbnail_url=None, thumbnail_width=None, thumbnail_height=None): + + def __init__(self, id: str, phone_number: str, first_name: str, last_name: Optional[str] = None, vcard: Optional[str] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, + thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None): super().__init__('contact', id, input_message_content = input_message_content, reply_markup = reply_markup) - self.phone_number = phone_number - self.first_name = first_name - self.last_name = last_name - self.vcard = vcard - self.thumbnail_url = thumbnail_url - self.thumbnail_width = thumbnail_width - self.thumbnail_height = thumbnail_height + self.phone_number: str = phone_number + self.first_name: str = first_name + self.last_name: Optional[str] = last_name + self.vcard: Optional[str] = vcard + self.thumbnail_url: Optional[str] = thumbnail_url + self.thumbnail_width: Optional[int] = thumbnail_width + self.thumbnail_height: Optional[int] = thumbnail_height + @property - def thumb_url(self): + def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property - def thumb_width(self): + def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property - def thumb_height(self): + def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height @@ -5352,9 +5382,9 @@ class InlineQueryResultGame(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultGame` """ - def __init__(self, id, game_short_name, reply_markup=None): + def __init__(self, id: str, game_short_name: str, reply_markup: Optional[InlineKeyboardMarkup] = None): super().__init__('game', id, reply_markup = reply_markup) - self.game_short_name = game_short_name + self.game_short_name: str = game_short_name def to_dict(self): json_dict = super().to_dict() @@ -5367,17 +5397,17 @@ class InlineQueryResultCachedBase(ABC, JsonSerializable): Base class of all InlineQueryResultCached* classes. """ def __init__(self): - self.type = None - self.id = None - self.title = None - self.description = None - self.caption = None - self.reply_markup = None - self.input_message_content = None - self.parse_mode = None - self.caption_entities = None - self.payload_dic = {} - self.show_caption_above_media = None + self.type: str = None + self.id: str = None + self.title: Optional[str] = None + self.description: Optional[str] = None + self.caption: Optional[str] = None + self.reply_markup: Optional[InlineKeyboardMarkup] = None + self.input_message_content: Optional[InputMessageContent] = None + self.parse_mode: Optional[str] = None + self.caption_entities: Optional[List[MessageEntity]] = None + self.payload_dic: Dict[str] = {} + self.show_caption_above_media: Optional[bool] = None def to_json(self): json_dict = self.payload_dic @@ -5447,24 +5477,27 @@ class InlineQueryResultCachedPhoto(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedPhoto` """ - def __init__(self, id, photo_file_id, title=None, description=None, - caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None, show_caption_above_media=None): + def __init__(self, id: str, photo_file_id: str, title: Optional[str] = None, description: Optional[str] = None, + caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): + InlineQueryResultCachedBase.__init__(self) - self.type = 'photo' - self.id = id - self.photo_file_id = photo_file_id - self.title = title - self.description = description - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'photo' + self.id: str = id + self.photo_file_id: str = photo_file_id + self.title: Optional[str] = title + self.description: Optional[str] = description + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['photo_file_id'] = photo_file_id self.show_caption_above_media: Optional[bool] = show_caption_above_media + # noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedGif(InlineQueryResultCachedBase): """ @@ -5506,20 +5539,22 @@ class InlineQueryResultCachedGif(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedGif` """ - def __init__(self, id, gif_file_id, title=None, description=None, - caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None, show_caption_above_media=None): + def __init__(self, id: str, gif_file_id: str, title: Optional[str] = None, description: Optional[str] = None, + caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): + InlineQueryResultCachedBase.__init__(self) - self.type = 'gif' - self.id = id - self.gif_file_id = gif_file_id - self.title = title - self.description = description - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'gif' + self.id: str = id + self.gif_file_id: str = gif_file_id + self.title: Optional[str] = title + self.description: Optional[str] = description + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['gif_file_id'] = gif_file_id self.show_caption_above_media: Optional[bool] = show_caption_above_media @@ -5565,20 +5600,22 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedMpeg4Gif` """ - def __init__(self, id, mpeg4_file_id, title=None, description=None, - caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None, show_caption_above_media=None): + def __init__(self, id: str, mpeg4_file_id: str, title: Optional[str] = None, description: Optional[str] = None, + caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): + InlineQueryResultCachedBase.__init__(self) - self.type = 'mpeg4_gif' - self.id = id - self.mpeg4_file_id = mpeg4_file_id - self.title = title - self.description = description - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'mpeg4_gif' + self.id: str = id + self.mpeg4_file_id: str = mpeg4_file_id + self.title: Optional[str] = title + self.description: Optional[str] = description + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['mpeg4_file_id'] = mpeg4_file_id self.show_caption_above_media: Optional[bool] = show_caption_above_media @@ -5607,16 +5644,18 @@ class InlineQueryResultCachedSticker(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedSticker` """ - def __init__(self, id, sticker_file_id, reply_markup=None, input_message_content=None): + def __init__(self, id: str, sticker_file_id: str, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None): InlineQueryResultCachedBase.__init__(self) - self.type = 'sticker' - self.id = id - self.sticker_file_id = sticker_file_id - self.reply_markup = reply_markup - self.input_message_content = input_message_content + self.type: str = 'sticker' + self.id: str = id + self.sticker_file_id: str = sticker_file_id + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content self.payload_dic['sticker_file_id'] = sticker_file_id + # noinspection PyUnresolvedReferences,PyShadowingBuiltins class InlineQueryResultCachedDocument(InlineQueryResultCachedBase): """ @@ -5659,20 +5698,23 @@ class InlineQueryResultCachedDocument(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedDocument` """ - def __init__(self, id, document_file_id, title, description=None, - caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, input_message_content=None): + + def __init__(self, id: str, document_file_id: str, title: str, description: Optional[str] = None, + caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None): + InlineQueryResultCachedBase.__init__(self) - self.type = 'document' - self.id = id - self.document_file_id = document_file_id - self.title = title - self.description = description - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'document' + self.id: str = id + self.title: str = title + self.document_file_id: str = document_file_id + self.description: Optional[str] = description + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['document_file_id'] = document_file_id @@ -5721,21 +5763,23 @@ class InlineQueryResultCachedVideo(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedVideo` """ - def __init__(self, id, video_file_id, title, description=None, - caption=None, caption_entities = None, parse_mode=None, - reply_markup=None, - input_message_content=None, show_caption_above_media=None): + + def __init__(self, id: str, video_file_id: str, title: str, description: Optional[str] = None, + caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): + InlineQueryResultCachedBase.__init__(self) - self.type = 'video' - self.id = id - self.video_file_id = video_file_id - self.title = title - self.description = description - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'video' + self.id: str = id + self.video_file_id: str = video_file_id + self.title: str = title + self.description: Optional[str] = description + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['video_file_id'] = video_file_id self.show_caption_above_media: Optional[bool] = show_caption_above_media @@ -5779,19 +5823,22 @@ class InlineQueryResultCachedVoice(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedVoice` """ - def __init__(self, id, voice_file_id, title, caption=None, caption_entities = None, - parse_mode=None, reply_markup=None, input_message_content=None): + + def __init__(self, id: str, voice_file_id: str, title: str, caption: Optional[str] = None, + caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, + reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): InlineQueryResultCachedBase.__init__(self) - self.type = 'voice' - self.id = id - self.voice_file_id = voice_file_id - self.title = title - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'voice' + self.id: str = id + self.voice_file_id: str = voice_file_id + self.title: str = title + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['voice_file_id'] = voice_file_id + # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -5830,17 +5877,19 @@ class InlineQueryResultCachedAudio(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedAudio` """ - def __init__(self, id, audio_file_id, caption=None, caption_entities = None, - parse_mode=None, reply_markup=None, input_message_content=None): + + def __init__(self, id: str, audio_file_id: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, + input_message_content: Optional[InputMessageContent] = None): InlineQueryResultCachedBase.__init__(self) - self.type = 'audio' - self.id = id - self.audio_file_id = audio_file_id - self.caption = caption - self.caption_entities = caption_entities - self.reply_markup = reply_markup - self.input_message_content = input_message_content - self.parse_mode = parse_mode + self.type: str = 'audio' + self.id: str = id + self.audio_file_id: str = audio_file_id + self.caption: Optional[str] = caption + self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup + self.input_message_content: Optional[InputMessageContent] = input_message_content + self.parse_mode: Optional[str] = parse_mode self.payload_dic['audio_file_id'] = audio_file_id @@ -5887,7 +5936,7 @@ def de_json(cls, json_string): return cls(**obj) @classmethod - def parse_photo(cls, photo_size_array): + def parse_photo(cls, photo_size_array) -> List[PhotoSize]: """ Parse the photo array into a list of PhotoSize objects """ @@ -5897,7 +5946,7 @@ def parse_photo(cls, photo_size_array): return ret @classmethod - def parse_entities(cls, message_entity_array): + def parse_entities(cls, message_entity_array) -> List[MessageEntity]: """ Parse the message entity array into a list of MessageEntity objects """ @@ -5968,16 +6017,16 @@ def __init__(self, file_id, file_unique_id, width=None, height=None, duration=No thumbnail=None, file_name=None, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id - self.width: int = width - self.height: int = height - self.duration: int = duration - self.thumbnail: PhotoSize = thumbnail - self.file_name: str = file_name - self.mime_type: str = mime_type - self.file_size: int = file_size + self.width: Optional[int] = width + self.height: Optional[int] = height + self.duration: Optional[int] = duration + self.thumbnail: Optional[PhotoSize] = thumbnail + self.file_name: Optional[str] = file_name + self.mime_type: Optional[str] = mime_type + self.file_size: Optional[int] = file_size @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6007,7 +6056,7 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj['user']) return cls(**obj) - def __init__(self, position, user, score, **kwargs): + def __init__(self, position: int, user: User, score: int, **kwargs): self.position: int = position self.user: User = user self.score: int = score @@ -6158,8 +6207,8 @@ def de_json(cls, json_string): def __init__(self, name=None, phone_number=None, email=None, shipping_address=None, **kwargs): self.name: str = name self.phone_number: str = phone_number - self.email: str = email - self.shipping_address: ShippingAddress = shipping_address + self.email: Optional[str] = email + self.shipping_address: Optional[ShippingAddress] = shipping_address # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -6186,7 +6235,7 @@ def __init__(self, id, title): self.title: str = title self.prices: List[LabeledPrice] = [] - def add_price(self, *args): + def add_price(self, *args) -> 'ShippingOption': """ Add LabeledPrice to ShippingOption @@ -6341,8 +6390,8 @@ def __init__(self, id, from_user, currency, total_amount, invoice_payload, shipp self.currency: str = currency self.total_amount: int = total_amount self.invoice_payload: str = invoice_payload - self.shipping_option_id: str = shipping_option_id - self.order_info: OrderInfo = order_info + self.shipping_option_id: Optional[str] = shipping_option_id + self.order_info: Optional[OrderInfo] = order_info # Stickers @@ -6390,15 +6439,15 @@ def __init__(self, name, title, sticker_type, stickers, thumbnail=None, **kwargs self.title: str = title self.sticker_type: str = sticker_type self.stickers: List[Sticker] = stickers - self.thumbnail: PhotoSize = thumbnail + self.thumbnail: Optional[PhotoSize] = thumbnail @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @property - def contains_masks(self): + def contains_masks(self) -> bool: """ Deprecated since Bot API 6.2, use sticker_type instead. """ @@ -6406,7 +6455,7 @@ def contains_masks(self): return self.sticker_type == 'mask' @property - def is_animated(self): + def is_animated(self) -> bool: """ Deprecated since Bot API 7.2. Stickers can be mixed now. """ @@ -6414,7 +6463,7 @@ def is_animated(self): return False @property - def is_video(self): + def is_video(self) -> bool: """ Deprecated since Bot API 7.2. Stickers can be mixed now. """ @@ -6506,17 +6555,17 @@ def __init__(self, file_id, file_unique_id, type, width, height, is_animated, self.height: int = height self.is_animated: bool = is_animated self.is_video: bool = is_video - self.thumbnail: PhotoSize = thumbnail - self.emoji: str = emoji - self.set_name: str = set_name - self.mask_position: MaskPosition = mask_position - self.file_size: int = file_size - self.premium_animation: File = premium_animation - self.custom_emoji_id: int = custom_emoji_id - self.needs_repainting: bool = needs_repainting + self.thumbnail: Optional[PhotoSize] = thumbnail + self.emoji: Optional[str] = emoji + self.set_name: Optional[str] = set_name + self.mask_position: Optional[MaskPosition] = mask_position + self.file_size: Optional[int] = file_size + self.premium_animation: Optional[File] = premium_animation + self.custom_emoji_id: Optional[str] = custom_emoji_id + self.needs_repainting: Optional[bool] = needs_repainting @property - def thumb(self): + def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6646,7 +6695,9 @@ class InputMediaPhoto(InputMedia): :return: Instance of the class :rtype: :class:`telebot.types.InputMediaPhoto` """ - def __init__(self, media, caption=None, parse_mode=None, caption_entities=None, has_spoiler=None, show_caption_above_media=None): + def __init__(self, media: Union[str, InputFile], caption: Optional[str] = None, + parse_mode: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, + has_spoiler: Optional[bool] = None, show_caption_above_media: Optional[bool] = None): if service_utils.is_pil_image(media): media = service_utils.pil_image_to_file(media) @@ -6715,20 +6766,24 @@ class InputMediaVideo(InputMedia): :return: Instance of the class :rtype: :class:`telebot.types.InputMediaVideo` """ - def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption_entities=None, - width=None, height=None, duration=None, supports_streaming=None, has_spoiler=None, show_caption_above_media=None): + def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, InputFile]] = None, + caption: Optional[str] = None, parse_mode: Optional[str] = None, + caption_entities: Optional[List[MessageEntity]] = None, width: Optional[int] = None, + height: Optional[int] = None, duration: Optional[int] = None, + supports_streaming: Optional[bool] = None, has_spoiler: Optional[bool] = None, + show_caption_above_media: Optional[bool] = None): super(InputMediaVideo, self).__init__( type="video", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail = thumbnail - self.width = width - self.height = height - self.duration = duration - self.supports_streaming = supports_streaming + self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + self.width: Optional[int] = width + self.height: Optional[int] = height + self.duration: Optional[int] = duration + self.supports_streaming: Optional[bool] = supports_streaming self.has_spoiler: Optional[bool] = has_spoiler self.show_caption_above_media: Optional[bool] = show_caption_above_media @property - def thumb(self): + def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6798,19 +6853,24 @@ class InputMediaAnimation(InputMedia): :return: Instance of the class :rtype: :class:`telebot.types.InputMediaAnimation` """ - def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption_entities=None, - width=None, height=None, duration=None, has_spoiler=None, show_caption_above_media=None): + + def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, InputFile]] = None, + caption: Optional[str] = None, parse_mode: Optional[str] = None, + caption_entities: Optional[List[MessageEntity]] = None, width: Optional[int] = None, + height: Optional[int] = None, duration: Optional[int] = None, + has_spoiler: Optional[bool] = None, show_caption_above_media: Optional[bool] = None): super(InputMediaAnimation, self).__init__( type="animation", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail = thumbnail - self.width = width - self.height = height - self.duration = duration + self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + self.width: Optional[int] = width + self.height: Optional[int] = height + self.duration: Optional[int] = duration self.has_spoiler: Optional[bool] = has_spoiler self.show_caption_above_media: Optional[bool] = show_caption_above_media + @property - def thumb(self): + def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6872,17 +6932,19 @@ class InputMediaAudio(InputMedia): :return: Instance of the class :rtype: :class:`telebot.types.InputMediaAudio` """ - def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption_entities=None, - duration=None, performer=None, title=None): + def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, InputFile]] = None, + caption: Optional[str] = None, parse_mode: Optional[str] = None, + caption_entities: Optional[List[MessageEntity]] = None, duration: Optional[int] = None, + performer: Optional[str] = None, title: Optional[str] = None): super(InputMediaAudio, self).__init__( type="audio", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail = thumbnail - self.duration = duration - self.performer = performer - self.title = title + self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + self.duration: Optional[int] = duration + self.performer: Optional[str] = performer + self.title: Optional[str] = title @property - def thumb(self): + def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6935,15 +6997,17 @@ class InputMediaDocument(InputMedia): :return: Instance of the class :rtype: :class:`telebot.types.InputMediaDocument` """ - def __init__(self, media, thumbnail=None, caption=None, parse_mode=None, caption_entities=None, - disable_content_type_detection=None): + def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, InputFile]] = None, + caption: Optional[str] = None, parse_mode: Optional[str] = None, + caption_entities: Optional[List[MessageEntity]] = None, + disable_content_type_detection: Optional[bool] = None): super(InputMediaDocument, self).__init__( type="document", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail = thumbnail - self.disable_content_type_detection = disable_content_type_detection + self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + self.disable_content_type_detection: Optional[bool] = disable_content_type_detection @property - def thumb(self): + def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6985,7 +7049,7 @@ def de_json(cls, json_string): def __init__(self, text, voter_count = 0, text_entities=None, **kwargs): self.text: str = text self.voter_count: int = voter_count - self.text_entities: List[MessageEntity] = text_entities + self.text_entities: Optional[List[MessageEntity]] = text_entities # Converted in _convert_poll_options # def to_json(self): # # send_poll Option is a simple string: https://core.telegram.org/bots/api#sendpoll @@ -7010,10 +7074,11 @@ class InputPollOption(JsonSerializable): :return: Instance of the class :rtype: :class:`telebot.types.PollOption` """ - def __init__(self, text, text_parse_mode=None, text_entities=None, **kwargs): + def __init__(self, text: str, text_parse_mode: Optional[str] = None, text_entities: Optional[List[MessageEntity]] = None, + **kwargs): self.text: str = text self.text_parse_mode: Optional[str] = text_parse_mode - self.text_entities: List[MessageEntity] = text_entities + self.text_entities: Optional[List[MessageEntity]] = text_entities def to_json(self): return json.dumps(self.to_dict()) @@ -7095,13 +7160,13 @@ def de_json(cls, json_string): obj['question_entities'] = Message.parse_entities(obj['question_entities']) return cls(**obj) - # noinspection PyShadowingBuiltins def __init__( self, - question, options, - poll_id=None, total_voter_count=None, is_closed=None, is_anonymous=None, type=None, - allows_multiple_answers=None, correct_option_id=None, explanation=None, explanation_entities=None, - open_period=None, close_date=None, poll_type=None, question_entities=None, + question: str, options: List[PollOption], + poll_id: str = None, total_voter_count: int = None, is_closed: bool = None, is_anonymous: bool = None, + type: str = None, allows_multiple_answers: bool = None, correct_option_id: int = None, + explanation: str = None, explanation_entities: List[MessageEntity] = None, open_period: int = None, + close_date: int = None, poll_type: str = None, question_entities: List[MessageEntity] = None, **kwargs): self.id: str = poll_id self.question: str = question @@ -7167,10 +7232,10 @@ def de_json(cls, json_string): obj['voter_chat'] = Chat.de_json(obj['voter_chat']) return cls(**obj) - def __init__(self, poll_id, option_ids, user=None, voter_chat=None, **kwargs): + def __init__(self, poll_id: str, option_ids: List[int], user: Optional[User] = None, voter_chat: Optional[Chat] = None, **kwargs): self.poll_id: str = poll_id self.user: Optional[User] = user - self.option_ids: List[int] = option_ids + self.option_ids: Optional[List[int]] = option_ids self.voter_chat: Optional[Chat] = voter_chat @@ -7213,7 +7278,7 @@ def de_json(cls, json_string): obj['location'] = Location.de_json(obj['location']) return cls(**obj) - def __init__(self, location, address, **kwargs): + def __init__(self, location: Location, address: str, **kwargs): self.location: Location = location self.address: str = address @@ -7272,17 +7337,18 @@ def de_json(cls, json_string): obj['creator'] = User.de_json(obj['creator']) return cls(**obj) - def __init__(self, invite_link, creator, creates_join_request , is_primary, is_revoked, - name=None, expire_date=None, member_limit=None, pending_join_request_count=None, **kwargs): + def __init__(self, invite_link: str, creator: User, creates_join_request: bool, is_primary: bool, is_revoked: bool, + name: Optional[str] = None, expire_date: Optional[int] = None, member_limit: Optional[int] = None, + pending_join_request_count: Optional[int] = None, **kwargs): self.invite_link: str = invite_link self.creator: User = creator self.creates_join_request: bool = creates_join_request self.is_primary: bool = is_primary self.is_revoked: bool = is_revoked - self.name: str = name - self.expire_date: int = expire_date - self.member_limit: int = member_limit - self.pending_join_request_count: int = pending_join_request_count + self.name: Optional[str] = name + self.expire_date: Optional[int] = expire_date + self.member_limit: Optional[int] = member_limit + self.pending_join_request_count: Optional[int] = pending_join_request_count def to_json(self): return json.dumps(self.to_dict()) @@ -7472,7 +7538,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, message_auto_delete_time, **kwargs): - self.message_auto_delete_time = message_auto_delete_time + self.message_auto_delete_time: int = message_auto_delete_time class MenuButton(JsonDeserializable, JsonSerializable, Dictionaryable): @@ -7524,7 +7590,7 @@ class MenuButtonCommands(MenuButton): :rtype: :class:`telebot.types.MenuButtonCommands` """ - def __init__(self, type = None, **kwargs): + def __init__(self, type: str = None, **kwargs): self.type: str = "commands" def to_dict(self): @@ -7557,7 +7623,7 @@ class MenuButtonWebApp(MenuButton): :rtype: :class:`telebot.types.MenuButtonWebApp` """ - def __init__(self, type, text, web_app, **kwargs): + def __init__(self, type: str, text: str, web_app: WebAppInfo, **kwargs): self.type: str = "web_app" self.text: str = text self.web_app: WebAppInfo = web_app @@ -7582,7 +7648,7 @@ class MenuButtonDefault(MenuButton): :return: Instance of the class :rtype: :class:`telebot.types.MenuButtonDefault` """ - def __init__(self, type = None, **kwargs): + def __init__(self, type: str = None, **kwargs): self.type: str = "default" def to_dict(self): @@ -7661,10 +7727,10 @@ def de_json(cls, json_string): def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_delete_messages: bool, can_manage_video_chats: bool, can_restrict_members: bool, can_promote_members: bool, can_change_info: bool, can_invite_users: bool, - can_post_messages: bool=None, can_edit_messages: bool=None, - can_pin_messages: bool=None, can_manage_topics: bool=None, - can_post_stories: bool=None, can_edit_stories: bool=None, - can_delete_stories: bool=None, **kwargs + can_post_messages: Optional[bool]=None, can_edit_messages: Optional[bool]=None, + can_pin_messages: Optional[bool]=None, can_manage_topics: Optional[bool]=None, + can_post_stories: Optional[bool]=None, can_edit_stories: Optional[bool]=None, + can_delete_stories: Optional[bool]=None, **kwargs ) -> None: self.is_anonymous: bool = is_anonymous @@ -7675,13 +7741,13 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, self.can_promote_members: bool = can_promote_members self.can_change_info: bool = can_change_info self.can_invite_users: bool = can_invite_users - self.can_post_messages: bool = can_post_messages - self.can_edit_messages: bool = can_edit_messages - self.can_pin_messages: bool = can_pin_messages - self.can_manage_topics: bool = can_manage_topics - self.can_post_stories: bool = can_post_stories - self.can_edit_stories: bool = can_edit_stories - self.can_delete_stories: bool = can_delete_stories + self.can_post_messages: Optional[bool] = can_post_messages + self.can_edit_messages: Optional[bool] = can_edit_messages + self.can_pin_messages: Optional[bool] = can_pin_messages + self.can_manage_topics: Optional[bool] = can_manage_topics + self.can_post_stories: Optional[bool] = can_post_stories + self.can_edit_stories: Optional[bool] = can_edit_stories + self.can_delete_stories: Optional[bool] = can_delete_stories def to_dict(self): json_dict = { @@ -7773,14 +7839,14 @@ def _resolve_file(file): raise TypeError("File must be a string or a file-like object(pathlib.Path, io.IOBase).") @property - def file(self): + def file(self) -> Union[IOBase, str]: """ File object. """ return self._file @property - def file_name(self): + def file_name(self) -> str: """ File name. """ @@ -7965,9 +8031,9 @@ def de_json(cls, json_string): def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str]=None, from_attachment_menu: Optional[bool]=None, **kwargs) -> None: - self.web_app_name: str = web_app_name - self.from_request: bool = from_request - self.from_attachment_menu: bool = from_attachment_menu + self.web_app_name: Optional[str] = web_app_name + self.from_request: Optional[bool] = from_request + self.from_attachment_menu: Optional[bool] = from_attachment_menu class ChatShared(JsonDeserializable): @@ -8126,7 +8192,7 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) - def convert_input_sticker(self): + def convert_input_sticker(self) -> Tuple[dict, Optional[dict]]: if service_utils.is_string(self.sticker): return self.to_json(), None @@ -8167,13 +8233,14 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, query=None, allow_user_chats=None, allow_bot_chats=None, allow_group_chats=None, - allow_channel_chats=None, **kwargs): - self.query: str = query - self.allow_user_chats: bool = allow_user_chats - self.allow_bot_chats: bool = allow_bot_chats - self.allow_group_chats: bool = allow_group_chats - self.allow_channel_chats: bool = allow_channel_chats + def __init__(self, query: Optional[str]=None, allow_user_chats: Optional[bool]=None, allow_bot_chats: Optional[bool]=None, + allow_group_chats: Optional[bool]=None, allow_channel_chats: Optional[bool]=None) -> None: + self.query: Optional[str] = query + self.allow_user_chats: Optional[bool] = allow_user_chats + self.allow_bot_chats: Optional[bool] = allow_bot_chats + self.allow_group_chats: Optional[bool] = allow_group_chats + self.allow_channel_chats: Optional[bool] = allow_channel_chats + def to_dict(self): json_dict = {} @@ -9166,17 +9233,17 @@ def de_json(cls, json_string): obj['users'] = [SharedUser.de_json(user) for user in obj['users']] return cls(**obj) - def __init__(self, request_id, users: List[SharedUser], **kwargs): - self.request_id = request_id - self.users = users + def __init__(self, request_id: int, users: List[SharedUser], **kwargs): + self.request_id: int = request_id + self.users: List[SharedUser] = users @property - def user_id(self): + def user_id(self) -> int: logger.warning('The parameter "user_id" is deprecated, use "user_ids" instead') return None @property - def user_ids(self): + def user_ids(self) -> List[int]: logger.warning('The parameter "user_ids" is deprecated, use "users" instead') return self.users @@ -10586,9 +10653,9 @@ class InputPaidMedia(JsonSerializable): :rtype: :class:`InputPaidMediaPhoto` or :class:`InputPaidMediaVideo` """ - def __init__(self, type, media, **kwargs): - self.type = type - self.media = media + def __init__(self, type: str, media: Union[str, InputFile], **kwargs): + self.type: str = type + self.media: Union[str, InputFile] = media if service_utils.is_string(self.media): self._media_name = '' @@ -10625,7 +10692,7 @@ class InputPaidMediaPhoto(InputPaidMedia): :rtype: :class:`InputPaidMediaPhoto` """ - def __init__(self, media, **kwargs): + def __init__(self, media: Union[str, InputFile], **kwargs): super().__init__(type='photo', media=media) class InputPaidMediaVideo(InputPaidMedia): @@ -10665,14 +10732,16 @@ class InputPaidMediaVideo(InputPaidMedia): :rtype: :class:`InputPaidMediaVideo` """ - - def __init__(self, media, thumbnail=None, width=None, height=None, duration=None, supports_streaming=None, **kwargs): + def __init__(self, media: Union[str, InputFile], thumbnail: Optional[InputFile] = None, width: Optional[int] = None, + height: Optional[int] = None, duration: Optional[int] = None, supports_streaming: Optional[bool] = None, + **kwargs): super().__init__(type='video', media=media) - self.thumbnail = thumbnail - self.width = width - self.height = height - self.duration = duration - self.supports_streaming = supports_streaming + self.thumbnail: Optional[Union[str,InputFile]] = thumbnail + self.width: Optional[int] = width + self.height: Optional[int] = height + self.duration: Optional[int] = duration + self.supports_streaming: Optional[bool] = supports_streaming + def to_dict(self): data = super().to_dict() From 2ae6b9308e05dff5632f2e6bf91301b74d5cb7fc Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 27 Jul 2024 18:57:30 +0500 Subject: [PATCH 318/480] Use deepcopy for sync --- telebot/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index b154d04ca..671c5631b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -20,6 +20,7 @@ # random module to generate random string import random import string +import copy import ssl @@ -8749,7 +8750,7 @@ def _run_middlewares_and_handler(self, message, handlers, middlewares, update_ty logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function'])) return else: - data_copy = data.copy() + data_copy = copy.deepcopy(data) for key in list(data_copy): # remove data from data_copy if handler does not accept it if key not in params: From 74019d03afe7f0e0f4248c0cdf34655617256045 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 27 Jul 2024 18:58:07 +0500 Subject: [PATCH 319/480] Use deepcopy for async --- telebot/async_telebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d50cbf7e0..27b861ead 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -32,7 +32,7 @@ import string import random import ssl - +import copy """ Module : telebot @@ -558,7 +558,7 @@ async def _run_middlewares_and_handlers(self, message, handlers, middlewares, up logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function'])) return else: - data_copy = data.copy() + data_copy = copy.deepcopy(data) for key in list(data_copy): # remove data from data_copy if handler does not accept it if key not in params: From 2dbf19004c74a7f8e73f37a460484fdec023ccb3 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 28 Jul 2024 14:26:58 +0500 Subject: [PATCH 320/480] Remove apihelper following the validate_token not using getMe --- telebot/async_telebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d60a4a090..705012f77 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -18,7 +18,7 @@ from inspect import signature, iscoroutinefunction -from telebot import util, types, asyncio_helper, apihelper # have to use sync +from telebot import util, types, asyncio_helper import asyncio from telebot import asyncio_filters From b10e8d749440cc596fdba05b1c5d1a33e4b86196 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 28 Jul 2024 14:48:12 +0500 Subject: [PATCH 321/480] Reverted changes regarding self._user, fixed validate_token=False causing error when extracting a bot id --- telebot/__init__.py | 6 +----- telebot/async_telebot.py | 6 ++---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d0ab64d5a..19f85f2d2 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -195,8 +195,7 @@ def __init__( if validate_token: util.validate_token(self.token) - - self.bot_id = util.extract_bot_id(self.token) # subject to change in future, unspecified + self.bot_id = util.extract_bot_id(self.token) # subject to change in future, unspecified # logs-related if colorful_logs: @@ -1184,9 +1183,6 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F if restart_on_change: self._setup_change_detector(path_to_watch) - if not self._user: - self._user = self.get_me() - logger.info('Starting your bot with username: [@%s]', self.user.username) if self.threaded: diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 705012f77..5302000ff 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -193,8 +193,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ if validate_token: util.validate_token(self.token) - - self.bot_id: int = util.extract_bot_id(self.token) # subject to change, unspecified + self.bot_id: int = util.extract_bot_id(self.token) # subject to change, unspecified @property @@ -437,8 +436,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: # show warning logger.warning("Setting non_stop to False will stop polling on API and system exceptions.") - if not self._user: - self._user = await self.get_me() + self._user = await self.get_me() logger.info('Starting your bot with username: [@%s]', self.user.username) From 6108e358134177d07d90f5fe5907217140c51a40 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 28 Jul 2024 14:49:00 +0500 Subject: [PATCH 322/480] fix docstring --- telebot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 19f85f2d2..74c08a4b8 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6699,7 +6699,7 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ - Reset data for a user in chat: sets the 'data' fieldi to an empty dictionary. + Reset data for a user in chat: sets the 'data' field to an empty dictionary. :param user_id: User's identifier :type user_id: :obj:`int` From 9a8ca9d51e395569f81412449674ce218505f740 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 29 Jul 2024 00:02:37 +0300 Subject: [PATCH 323/480] Fix html_text for None --- telebot/types.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 6913452be..bd9688cb7 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1517,6 +1517,8 @@ def html_text(self): """ Returns html-rendered text. """ + if self.text is None: + return None return apply_html_entities(self.text, self.entities, getattr(self, "custom_subs", None)) @property @@ -9067,6 +9069,8 @@ def html_text(self): """ Returns html-rendered text. """ + if self.text is None: + return None return apply_html_entities(self.text, self.entities, getattr(self, "custom_subs", None)) From cd987101b3cab121d1d7c08be13b59b39f8618e3 Mon Sep 17 00:00:00 2001 From: EgorKhabarov Date: Mon, 29 Jul 2024 02:10:55 +0400 Subject: [PATCH 324/480] Fix html_caption for None. Return None instead if exception. --- telebot/types.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index bd9688cb7..9055091e9 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1526,6 +1526,8 @@ def html_caption(self): """ Returns html-rendered caption. """ + if self.caption is None: + return None return apply_html_entities(self.caption, self.caption_entities, getattr(self, "custom_subs", None)) @property From 30ebe756ac98010380a83114d84525ae968f0086 Mon Sep 17 00:00:00 2001 From: _run Date: Tue, 30 Jul 2024 15:48:26 +0500 Subject: [PATCH 325/480] make extract_bot_id return None in case validation fails --- telebot/__init__.py | 4 ++-- telebot/async_telebot.py | 4 ++-- telebot/util.py | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 74c08a4b8..fc7f3cdc3 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -191,11 +191,11 @@ def __init__( self.allow_sending_without_reply = allow_sending_without_reply self.webhook_listener = None self._user = None - self.bot_id: int = None if validate_token: util.validate_token(self.token) - self.bot_id = util.extract_bot_id(self.token) # subject to change in future, unspecified + + self.bot_id: Union[int, None] = util.extract_bot_id(self.token) # subject to change in future, unspecified # logs-related if colorful_logs: diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 5302000ff..ec782ff91 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -189,11 +189,11 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.middlewares = [] self._user = None # set during polling - self.bot_id: int = None if validate_token: util.validate_token(self.token) - self.bot_id: int = util.extract_bot_id(self.token) # subject to change, unspecified + + self.bot_id: Union[int, None] = util.extract_bot_id(self.token) # subject to change, unspecified @property diff --git a/telebot/util.py b/telebot/util.py index c8ef526c5..0448893e1 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -698,7 +698,11 @@ def validate_token(token) -> bool: return True -def extract_bot_id(token) -> str: +def extract_bot_id(token) -> Union[int, None]: + try: + validate_token(token) + except ValueError: + return None return int(token.split(':')[0]) From f0c3e5aec97fb2c86efaa84104ff5c3cb599d176 Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 31 Jul 2024 21:46:05 +0500 Subject: [PATCH 326/480] Bot api 7.8 --- README.md | 2 +- telebot/__init__.py | 15 +++++++++++---- telebot/apihelper.py | 8 ++++++-- telebot/async_telebot.py | 14 ++++++++++---- telebot/asyncio_helper.py | 8 ++++++-- telebot/types.py | 10 ++++++++-- 6 files changed, 42 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 98f8c389a..10d75993b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.7! +##

Supported Bot API version: 7.8!

Official documentation

Official ru documentation

diff --git a/telebot/__init__.py b/telebot/__init__.py index b154d04ca..70d59ddde 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4640,7 +4640,7 @@ def set_chat_description(self, chat_id: Union[int, str], description: Optional[s def pin_chat_message( self, chat_id: Union[int, str], message_id: int, - disable_notification: Optional[bool]=False) -> bool: + disable_notification: Optional[bool]=False, business_connection_id: Optional[str]=None) -> bool: """ Use this method to pin a message in a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -4659,15 +4659,19 @@ def pin_chat_message( to all group members about the new pinned message :type disable_notification: :obj:`bool` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: True on success. :rtype: :obj:`bool` """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification - return apihelper.pin_chat_message(self.token, chat_id, message_id, disable_notification=disable_notification) + return apihelper.pin_chat_message(self.token, chat_id, message_id, disable_notification=disable_notification, + business_connection_id=business_connection_id) - def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int]=None) -> bool: + def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int]=None, business_connection_id: Optional[str]=None) -> bool: """ Use this method to unpin specific pinned message in a supergroup chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -4682,10 +4686,13 @@ def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int] :param message_id: Int: Identifier of a message to unpin :type message_id: :obj:`int` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: True on success. :rtype: :obj:`bool` """ - return apihelper.unpin_chat_message(self.token, chat_id, message_id) + return apihelper.unpin_chat_message(self.token, chat_id, message_id, business_connection_id=business_connection_id) def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 0bcb80a96..2ee86abab 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1386,19 +1386,23 @@ def set_chat_description(token, chat_id, description): return _make_request(token, method_url, params=payload, method='post') -def pin_chat_message(token, chat_id, message_id, disable_notification=None): +def pin_chat_message(token, chat_id, message_id, disable_notification=None, business_connection_id=None): method_url = 'pinChatMessage' payload = {'chat_id': chat_id, 'message_id': message_id} if disable_notification is not None: payload['disable_notification'] = disable_notification + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') -def unpin_chat_message(token, chat_id, message_id): +def unpin_chat_message(token, chat_id, message_id, business_connection_id=None): method_url = 'unpinChatMessage' payload = {'chat_id': chat_id} if message_id: payload['message_id'] = message_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index d50cbf7e0..e702487f3 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6023,7 +6023,7 @@ async def set_chat_description(self, chat_id: Union[int, str], description: Opti async def pin_chat_message( self, chat_id: Union[int, str], message_id: int, - disable_notification: Optional[bool]=False) -> bool: + disable_notification: Optional[bool]=False, business_connection_id: Optional[str]=None) -> bool: """ Use this method to pin a message in a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -6042,14 +6042,17 @@ async def pin_chat_message( to all group members about the new pinned message :type disable_notification: :obj:`bool` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: True on success. :rtype: :obj:`bool` """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification - return await asyncio_helper.pin_chat_message(self.token, chat_id, message_id, disable_notification) + return await asyncio_helper.pin_chat_message(self.token, chat_id, message_id, disable_notification, business_connection_id) - async def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int]=None) -> bool: + async def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optional[int]=None, business_connection_id: Optional[str]=None) -> bool: """ Use this method to unpin specific pinned message in a supergroup chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -6064,10 +6067,13 @@ async def unpin_chat_message(self, chat_id: Union[int, str], message_id: Optiona :param message_id: Int: Identifier of a message to unpin :type message_id: :obj:`int` + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + :return: True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.unpin_chat_message(self.token, chat_id, message_id) + return await asyncio_helper.unpin_chat_message(self.token, chat_id, message_id, business_connection_id) async def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index b70508a2a..fa14f6123 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1365,19 +1365,23 @@ async def set_chat_description(token, chat_id, description): return await _process_request(token, method_url, params=payload, method='post') -async def pin_chat_message(token, chat_id, message_id, disable_notification=None): +async def pin_chat_message(token, chat_id, message_id, disable_notification=None, business_connection_id=None): method_url = 'pinChatMessage' payload = {'chat_id': chat_id, 'message_id': message_id} if disable_notification is not None: payload['disable_notification'] = disable_notification + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, method='post') -async def unpin_chat_message(token, chat_id, message_id): +async def unpin_chat_message(token, chat_id, message_id, business_connection_id=None): method_url = 'unpinChatMessage' payload = {'chat_id': chat_id} if message_id: payload['message_id'] = message_id + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, method='post') diff --git a/telebot/types.py b/telebot/types.py index 9055091e9..c5abb13d4 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -494,6 +494,9 @@ class User(JsonDeserializable, Dictionaryable, JsonSerializable): :param can_connect_to_business: Optional. True, if the bot can be connected to a Telegram Business account to receive its messages. Returned only in getMe. :type can_connect_to_business: :obj:`bool` + :param has_main_web_app: Optional. True, if the bot has a main Web App. Returned only in getMe. + :type has_main_web_app: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.User` """ @@ -506,7 +509,8 @@ def de_json(cls, json_string): # noinspection PyShadowingBuiltins def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, - is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, **kwargs): + is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, + has_main_web_app=None, **kwargs): self.id: int = id self.is_bot: bool = is_bot self.first_name: str = first_name @@ -519,6 +523,7 @@ def __init__(self, id, is_bot, first_name, last_name=None, username=None, langua self.is_premium: bool = is_premium self.added_to_attachment_menu: bool = added_to_attachment_menu self.can_connect_to_business: bool = can_connect_to_business + self.has_main_web_app: bool = has_main_web_app @property def full_name(self): @@ -545,7 +550,8 @@ def to_dict(self): 'supports_inline_queries': self.supports_inline_queries, 'is_premium': self.is_premium, 'added_to_attachment_menu': self.added_to_attachment_menu, - 'can_connect_to_business': self.can_connect_to_business} + 'can_connect_to_business': self.can_connect_to_business, + 'has_main_web_app': self.has_main_web_app} # noinspection PyShadowingBuiltins From a0b0b9b58c328216acb849317809e2bf46206c69 Mon Sep 17 00:00:00 2001 From: 2ei Date: Thu, 1 Aug 2024 22:00:23 +0300 Subject: [PATCH 327/480] Add Bot API badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98f8c389a..76f8f487e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: 7.7! +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From d059c648e0f8f37199b9c743ae387fd572607673 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 4 Aug 2024 10:20:53 +0300 Subject: [PATCH 328/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index cfa926801..1b8c80931 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.21.0' +release = '4.22.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 0095c3f21..a45a8dd3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.21.0" +version = "4.22.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 5016764c6..3bbf77eb0 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.21.0' +__version__ = '4.22.0' From adbf425e0253233a2b265b33dc2b61dbad50d056 Mon Sep 17 00:00:00 2001 From: nypava Date: Sun, 4 Aug 2024 15:00:22 +0300 Subject: [PATCH 329/480] add features to webapp --- examples/webapp/bot.py | 23 +- examples/webapp/webapp.html | 63 ------ examples/webapp/webapp/index.html | 163 ++++++++++++++ examples/webapp/webapp/script.js | 318 ++++++++++++++++++++++++++++ examples/webapp/webapp/style.css | 338 ++++++++++++++++++++++++++++++ 5 files changed, 836 insertions(+), 69 deletions(-) delete mode 100644 examples/webapp/webapp.html create mode 100644 examples/webapp/webapp/index.html create mode 100644 examples/webapp/webapp/script.js create mode 100644 examples/webapp/webapp/style.css diff --git a/examples/webapp/bot.py b/examples/webapp/bot.py index 310e25c5c..7fa106f09 100644 --- a/examples/webapp/bot.py +++ b/examples/webapp/bot.py @@ -1,16 +1,27 @@ from telebot import TeleBot -from telebot.types import ReplyKeyboardMarkup, KeyboardButton, WebAppInfo +from telebot.types import ( + ReplyKeyboardMarkup, + KeyboardButton, + WebAppInfo, + InlineKeyboardMarkup, + InlineKeyboardButton +) -BOT_TOKEN = '' -WEB_URL = 'https://pytelegrambotminiapp.vercel.app/' # https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/webapp/webapp.html +BOT_TOKEN = "" +WEB_URL = "https://pytelegrambotminiapp.vercel.app" # https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/webapp/webapp bot = TeleBot(BOT_TOKEN) @bot.message_handler(commands=["start"]) def start(message): - reply_markup = ReplyKeyboardMarkup(resize_keyboard=True) - reply_markup.row(KeyboardButton("Start MiniApp", web_app=WebAppInfo(WEB_URL))) - bot.reply_to(message, "Click the button to start MiniApp", reply_markup=reply_markup) + reply_keyboard_markup = ReplyKeyboardMarkup(resize_keyboard=True) + reply_keyboard_markup.row(KeyboardButton("Start MiniApp", web_app=WebAppInfo(WEB_URL))) + + inline_keyboard_markup = InlineKeyboardMarkup() + inline_keyboard_markup.row(InlineKeyboardButton('Start MiniApp', web_app=WebAppInfo(WEB_URL))) + + bot.reply_to(message, "Click the bottom inline button to start MiniApp", reply_markup=inline_keyboard_markup) + bot.reply_to(message, "Click keyboard button to start MiniApp", reply_markup=reply_keyboard_markup) @bot.message_handler(content_types=['web_app_data']) def web_app(message): diff --git a/examples/webapp/webapp.html b/examples/webapp/webapp.html deleted file mode 100644 index e2e953825..000000000 --- a/examples/webapp/webapp.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - MiniApp example - - - - -
- - -
- - - - - - - diff --git a/examples/webapp/webapp/index.html b/examples/webapp/webapp/index.html new file mode 100644 index 000000000..6f7d79ff7 --- /dev/null +++ b/examples/webapp/webapp/index.html @@ -0,0 +1,163 @@ + + + + + + + PyTelegramBotApi MiniApp + + + +
+ + +
+ +

client buttons

+
+ + + +
+

hapticFeedback (notification)

+ + +

tweak color [Bot API 6.1+]

+
+
+

Header color:

+
+
+
+
+
+
+
+
+

Background color:

+
+
+
+
+
+
+
+
+ +

popup and alert [Bot API 6.2+]

+ + +

request [Bot API 6.9+]

+
+ + + +
+ +

story [Bot API 7.8+]

+
+ + + +
+ +

cloud storage [Bot API 6.9+]

+
+
+ + +
+ + + + + + + + + + +
key value
- -
+
+ + +
+
+

data from telegram

+
+
+

initDataUnsafe

+
+
+

ThemeParams

+
+
+

Biometrics Manager

+ + + + + +
supportUnsupported in this platform
+
+
+ +

event from telegram

+
+
+
+
+ +

vertical scroll behaviour [Bot API 7.7+]

+
+

close the miniapp when scroll vertically

+
+ + +
+
+ +

closing confirmation [Bot API 6.2+]

+
+

Confimation dialog when closing mini app

+
+ + +
+
+ +

links

+ + +

other

+
+ + + +
+ +
+
 version: 
+
 platform: 
+
 color scheme: 
+
+ + + diff --git a/examples/webapp/webapp/script.js b/examples/webapp/webapp/script.js new file mode 100644 index 000000000..42889b055 --- /dev/null +++ b/examples/webapp/webapp/script.js @@ -0,0 +1,318 @@ +const telegram = Telegram.WebApp; +telegram.ready(); + +class ModifyStyle{ + constructor(element) { + this.element = element; + }; + disableButton() { + this.element.style.backgroundColor = 'transparent'; + this.element.style.color = 'var(--tg-theme-button-color)'; + this.element.style.border = "solid 1px var(--tg-theme-button-color)"; + }; + enableButton() { + this.element.style.backgroundColor = "var(--tg-theme-button-color)"; + this.element.style.color = 'var(--tg-theme-text-color)'; + }; +}; + +class TableModify{ + constructor(element) { + this.element = element; + } + addElements(element_1, element_2) { + this.element.innerHTML += ` ${element_1} ${element_2} `; + } + removeElement(id) { + document.getElementById(id).remove(); + } +}; + +const button = { + send_message : document.getElementById('send-message-button'), + back : document.getElementById('back-button'), + main: document.getElementById('main-button'), + settings: document.getElementById('settings-button'), + success: document.getElementById('success-button'), + warning: document.getElementById('warning-button'), + error: document.getElementById('error-button'), + popup: document.getElementById('popup-button'), + alert: document.getElementById('alert-button'), + confirm: document.getElementById('confirm-button'), + contact: document.getElementById('contact-button'), + write_access: document.getElementById('write-access-button'), + biometrics: document.getElementById('biometrics-button'), + cloud_add: document.getElementById('cloud-add-button'), + cloud_remove: document.getElementById('cloud-remove-button'), + vertical_scroll_enable: document.getElementById('enable-scroll-button'), + vertical_scroll_disable: document.getElementById('disable-scroll-button'), + close_confirm_enable: document.getElementById('enable-close-confirm-button'), + close_confirm_disable: document.getElementById('disable-close-confirm-button'), + post_story_photo: document.getElementById('post-story-photo-button'), + post_story_video: document.getElementById('post-story-video-button'), + post_story_with_link: document.getElementById('post-story-with-link-button'), + show_QR: document.getElementById('show-QR-button') , + expand: document.getElementById('expand-button'), + close: document.getElementById('close-button'), +}; + +const input = { + message: document.querySelector('.send-message__input'), + cloud_add_key: document.querySelector('.cloud-storage__input_add-key'), + cloud_add_value: document.querySelector('.cloud-storage__input_add-value'), + cloud_remove_key: document.querySelector('.cloud-storage__input_remove'), +}; + +const text = { + telegram_link: document.getElementById('telegram-link'), + internal_link: document.getElementById('internal-link'), + version: document.getElementById('version-text'), + platform: document.getElementById('platform-text'), + color_scheme: document.getElementById('color-scheme-text') +}; + +const table = { + cloud_table: document.querySelector(".cloud-storage__table"), + biometrics_table: document.getElementById("biometrics-table") +} + +const colors_tweaks = [ + document.getElementById('header-yellow'), + document.getElementById('header-button_color'), + document.getElementById('header-red'), + document.getElementById('header-default'), + document.getElementById('background-yellow'), + document.getElementById('background-button_color'), + document.getElementById('background-red'), + document.getElementById('background-default'), +]; + +telegram.MainButton.setParams({text: 'Close', color: '#ba4d47'}); +telegram.MainButton.onClick(() => {telegram.close()}); +telegram.MainButton.show(); +telegram.enableVerticalSwipes(); + +telegram.CloudStorage.getKeys((error, keys) => { + let table_modify = new TableModify(table.cloud_table); + if (keys.length) {table_modify.removeElement("null-storage-row")}; + keys.forEach((key) => { + telegram.CloudStorage.getItem(key, (error, item) => { + table_modify.addElements(key, item) + }); + }); +}); + +document.getElementById('initDataUnsafe-block').innerHTML += `
 ${JSON.stringify(telegram.initDataUnsafe, null, 2)} 
`; +document.getElementById('themeParams-block').innerHTML += `
 ${JSON.stringify(telegram.themeParams, null, 2)} 
`; + +let biometrics_table_modify = new TableModify(table.biometrics_table); + +telegram.BiometricManager.init(() => {['isInited', 'isBiometricAvailable', 'biometricType', 'isAccessRequested', 'isAccessGranted', 'isBiometricTokenSaved', 'deviceId'].forEach((field) => { + biometrics_table_modify.addElements(field, eval(`telegram.BiometricManager.${field}`)); +}); biometrics_table_modify.removeElement('null-biometrics-row') }); + +['themeChanged', 'viewportChanged', 'mainButtonClicked', 'backButtonClicked', 'settingsButtonClicked', 'invoiceClosed', 'popupClosed', 'qrTextReceived', 'scanQrPopupClosed', +'clipboardTextReceived', 'writeAccessRequested', 'contactRequested', 'biometricManagerUpdated', 'biometricAuthRequested', 'biometricTokenUpdated'].forEach((element) => { + telegram.onEvent(element, () => { + document.getElementById('event-block').innerHTML += `

${element}

`; + }); +}); + +text.color_scheme.innerText += telegram.colorScheme; +text.version.innerText += telegram.version; +text.platform.innerText += telegram.platform; + +button.send_message.addEventListener('click', () => { + telegram.sendData(input.message.value); + if (telegram.initDataUnsafe) telegram.showAlert('SendData only works in webapp that opened with reply keyboard.') + input.message.value = '' +}); + +button.main.addEventListener('click', (e) => { + const modify_button = new ModifyStyle(e.currentTarget); + if (e.currentTarget.value == 'enable') { + e.currentTarget.value = 'disable'; + modify_button.disableButton(); + telegram.MainButton.hide(); + } else { + e.currentTarget.value = 'enable'; + modify_button.enableButton(); + telegram.MainButton.show(); + } +}); + +button.back.addEventListener('click', (e) => { + const modify_button = new ModifyStyle(e.currentTarget); + if (e.currentTarget.value == 'enable') { + e.currentTarget.value = 'disable'; + modify_button.disableButton(); + telegram.BackButton.hide(); + } else { + e.currentTarget.value = 'enable'; + modify_button.enableButton(); + telegram.BackButton.show(); + } +}); + +button.settings.addEventListener('click', (e) => { + const modify_button = new ModifyStyle(e.currentTarget); + if (e.currentTarget.value == 'enable') { + e.currentTarget.value = 'disable'; + modify_button.disableButton(); + telegram.SettingsButton.hide(); + } else { + e.currentTarget.value = 'enable'; + modify_button.enableButton(); + telegram.SettingsButton.show(); + } +}); + +button.success.addEventListener('click', () => { + telegram.HapticFeedback.notificationOccurred('success'); +}); + +button.warning.addEventListener('click', () => { + telegram.HapticFeedback.notificationOccurred('warning'); +}); + +button.error.addEventListener('click', () => { + telegram.HapticFeedback.notificationOccurred('error'); +}); + +button.popup.addEventListener('click', () => { + telegram.showPopup({title: 'popup', message: 'this is popup message', buttons: [{ text: 'roger'}]}); +}); + +button.alert.addEventListener('click', () => { + telegram.showAlert('This is alert message'); +}); + +button.confirm.addEventListener('click', () => { + telegram.showConfirm('This is confirm message'); +}); + +button.contact.addEventListener('click', () => { + telegram.requestContact(); +}); + +button.write_access.addEventListener('click', () => { + telegram.requestWriteAccess(); +}); + +button.biometrics.addEventListener('click', () => { + telegram.BiometricManager.requestAccess({'reseaon': 'this is biometrics request'}); +}); + +button.vertical_scroll_enable.addEventListener('click', (e) => { + const modify_scroll_enable = new ModifyStyle(e.currentTarget); + const modify_scroll_disable = new ModifyStyle(button.vertical_scroll_disable); + if (e.currentTarget.value == 'disable') { + e.currentTarget.value = 'enable'; + modify_scroll_enable.enableButton(); + modify_scroll_disable.disableButton(); + button.vertical_scroll_disable.value = 'disable'; + telegram.enableVerticalSwipes(); + }; +}); + +button.vertical_scroll_disable.addEventListener('click', (e) => { + const modify_scroll_disable = new ModifyStyle(e.currentTarget); + const modify_scroll_enable = new ModifyStyle(button.vertical_scroll_enable); + if (e.currentTarget.value == 'disable') { + e.currentTarget.value = 'enable'; + modify_scroll_disable.enableButton(); + modify_scroll_enable.disableButton(); + telegram.disableVerticalSwipes(); + button.vertical_scroll_enable.value = 'disable'; + }; +}); + +button.close_confirm_enable.addEventListener('click', (e) => { + const modify_close_confirm_enable = new ModifyStyle(e.currentTarget); + const modify_close_confirm_disable = new ModifyStyle(button.close_confirm_disable); + if (e.currentTarget.value == 'disable') { + e.currentTarget.value = 'enable'; + modify_close_confirm_enable.enableButton(); + modify_close_confirm_disable.disableButton(); + button.close_confirm_disable.value = 'disable'; + telegram.enableClosingConfirmation(); + }; +}); + +button.close_confirm_disable.addEventListener('click', (e) => { + const modify_close_confirm_disable= new ModifyStyle(e.currentTarget); + const modify_close_confirm_enable= new ModifyStyle(button.close_confirm_enable); + if (e.currentTarget.value == 'disable') { + e.currentTarget.id = 'enable'; + modify_close_confirm_enable.disableButton(); + modify_close_confirm_disable.enableButton(); + button.close_confirm_enable.value = 'disable'; + telegram.disableClosingConfirmation(); + }; +}); + +button.show_QR.addEventListener('click', () => { + telegram.showScanQrPopup({text: "this is QR scanner"}); +}); + +button.expand.addEventListener('click', () => { + telegram.expand(); +}); + +button.close.addEventListener('click', () => { + telegram.close(); +}); + +button.cloud_add.addEventListener('click', () => { + let table_modify = new TableModify(table.cloud_table); + telegram.CloudStorage.setItem(input.cloud_add_key.value, input.cloud_add_value.value, (error, is_stored) => { + if (!is_stored) telegram.showAlert(error); + else { + table_modify.addElements(input.cloud_add_key.value, input.cloud_add_value.value); + new TableModify(table.cloud_table).removeElement('null-storage-row'); + }; + input.cloud_add_key.value = ''; + input.cloud_add_value.value = ''; + }); +}); + +button.cloud_remove.addEventListener('click', () => { + let table_modify = new TableModify(table.cloud_table); + telegram.CloudStorage.removeItem(input.cloud_remove_key.value, (error, is_removed) => { + if (!is_removed) telegram.showAlert(error); + else table_modify.removeElement(input.cloud_remove_key.value); + input.cloud_remove_key.value = ''; + }); +}); + +button.post_story_photo.addEventListener('click', () => { + telegram.shareToStory('https://telegra.ph/file/e194a37aed103485469b4.jpg', {text: 'This is photo story'}); +}); + +button.post_story_video.addEventListener('click', () => { + telegram.shareToStory('https://telegra.ph/file/16ffd9385a017b59f458e.mp4', {text: 'This is video story'}); +}); + +button.post_story_with_link.addEventListener('click', () => { + telegram.shareToStory('https://telegra.ph/file/e194a37aed103485469b4.jpg', {text: 'This is story with link', widget_link: {url: 'https://t.me/joinchat/Bn4ixj84FIZVkwhk2jag6A'}}); +}); + +colors_tweaks.forEach((element) => { + element.addEventListener('click', (e) => { + const color = window.getComputedStyle(e.currentTarget).backgroundColor; + if (e.currentTarget.id.includes('header')){ + telegram.setHeaderColor(color); + } else { + telegram.setBackgroundColor(color); + document.querySelector('.body').style.backgroundColor = telegram.backgroundColor; + }; + }); +}); + +text.telegram_link.addEventListener('click', () => { + telegram.openTelegramLink("https://t.me/joinchat/Bn4ixj84FIZVkwhk2jag6A"); +}); + +text.internal_link.addEventListener('click', () => { + telegram.openLink('https://telegram.org', {try_instant_view: false}); +}); diff --git a/examples/webapp/webapp/style.css b/examples/webapp/webapp/style.css new file mode 100644 index 000000000..30fad466c --- /dev/null +++ b/examples/webapp/webapp/style.css @@ -0,0 +1,338 @@ +:root { + --red-color: #ba4d47; + --yellow-color: #bab05b; +} + +.body { + background-color: (--tg-theme-secondary-bg-color); +} + +* { + font-family: Arial, Helvetica, sans-serif; + margin: 0; + padding: 0; +} + +input { + color: var(--tg-theme-text-color); +} + +table { + width: 93vw; + border-collapse: collapse; + border: solid 0px var(--tg-theme-hint-color); + border-radius: 5px; +} + +th { + font-weight: bold; +} + +td { + font-weight: lighter; + max-width: 46.5vw; + overflow-x: hidden; +} + + +th, td { + padding: 3px; + font-size: 14px; + color: var(--tg-theme-text-color); + text-align: center; + border: solid 1px var(--tg-theme-hint-color); +} + +input:focus { + outline: none; +} + +::placeholder { + color: var(--tg-theme-hint-color); +} + +.content-block { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 9.24px; + background-color: var(--tg-theme-bg-color); + height: 70px; +} + +.content-block_send-message { + flex-direction: column; + height: 160px; +} + +.content-block_tweak-color { + flex-direction: column; + align-items: start; + justify-content: center; + gap: 17px; + height: 96px; +} + +.content-block_cloud-storage { + flex-direction: column; + height: 320px; + gap: 9.6px; +} + +.content-block_link { + height: 104px; + flex-direction: column; +} + +.content-block_event{ + height: 220px; +} + +.content-block_scroll-behaviour, .content-block_close-confirmation { + height: 100px; + align-items: flex-start; + align-self: flex-start; + flex-direction: column; + padding-left: 4.2vw; +} + +.content-block_data { + height: 100%; + flex-direction: column; + align-items: flex-start; + padding:5vh 3vw 5vh 3vw ; + overflow: hidden; +} + +.scroll-behaviour__toggle-box, .content-block__toggle-box { + display: flex; + gap: 9.6px; +} + +.link__content { + display: flex; + flex-direction: row; +} + +.tweak-color__header, .tweak-color__background { + display: flex; + flex-direction: row; + justify-content: flex-end; + gap: 9.6px; + width: 65vw; +} + +.tweak-color__circle-block { + display: flex; + flex-direction: row; + gap: 2vw; +} + +.event__content { + overflow-y: auto; + height: 170px; + width: 88vw; + border: solid 1px var(--tg-theme-hint-color); + border-radius: 5px; + padding: 10px; +} + +.data__content { + padding-top: 10px; + padding-bottom: 10px; +} + +.cloud-storage__input-block { + width: 93vw; + display: flex; + flex-direction: row; + gap: 0px; +} + +.cloud-storage__input-block_remove { + width: 94vw; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.description-block { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + margin: 10px; + gap: 3px; +} + +.send-message__button{ + border: none; + color: var(--tg-theme-text-color); + background-color: var(--tg-theme-button-color); + border-radius: 5px; + width: 70vw; + height: 40px; +} + +.default-button { + color: var(--tg-theme-text-color); + background-color: var(--tg-theme-button-color); + border: none; + border-radius: 5px; + width: 29vw;; + height: 35px; +} + +.default-button_yellow { + background-color: var(--yellow-color); +} + +.default-button_red { + background-color: var(--red-color); +} + +.default-button_disable { + background: transparent; + color: var(--tg-theme-button-color); + border: solid 1px var(--tg-theme-button-color); +} + +.cloud-storage__button { + border: none; + border-radius: 5px; + color: var(--button_text_color); + width: 93vw; + height: 38px; +} + +.cloud-storage__button_add { + color: var(--tg-theme-text-color); + background-color: var(--tg-theme-button-color); + margin-bottom: 10px; +} + +.cloud-storage__button_remove { + color: var(--tg-theme-text-color); + background-color: var(--red-color); +} + +.header-text { + font-size: 14px; + color: var(--tg-theme-hint-color); + margin-top: 13px; + margin-bottom: 5px; + margin-left: 6px; +} + +.content-block__text { + color: var(--tg-theme-text-color); + font-size: 14px; + padding-bottom: 3px; +} + +.tweak-color__text { + font-size: 13px; + color: var(--tg-theme-text-color); + } + +.data__text { + color: var(--tg-theme-text-color); + font-weight: 300; + font-size: 15px; +} + +.link__text { + font-size: 14px; + color: var(--tg-theme-hint-color); + padding: 2px; +} + +.link__text_blue { + color: var(--tg-theme-link-color); +} + +.event__text { + color: var(--tg-theme-text-color); + font-weight: lighter; + font-size: 13px; +} + + +.description__text { + color: var(--tg-theme-hint-color); + font-size: 13px; + font-weight: 300; +} + +.send-message__input { + border: solid var(--tg-theme-hint-color) 1px; + background-color: transparent; + border-radius: 5px; + width: 67vw; + height: 40px; + padding-left: 10px; +} + +.cloud-storage__input { + border: solid 1px var(--tg-theme-hint-color); + background-color: transparent; + height: 30px; + padding-left: 10px; +} + +.cloud-storage__input_add-key { + border-radius: 5px 0px 0px 5px; + width: 35%; +} + +.cloud-storage__input_add-value { + border-radius: 0px 5px 5px 0px; + width: 65%; +} + +.cloud-storage__input_remove { + width: 90vw; + border: solid 1px var(--tg-theme-hint-color); + border-radius: 5px; + margin-bottom: 10px; +} + +.tweak-color__circle { + border-radius: 100%; + width: 20px; + height: 20px; +} + +.tweak-color__circle_yellow { + background-color: var(--yellow-color); +} + +.tweak-color__circle_red { + background-color: var(--red-color); +} + +.tweak-color__circle_button { + background-color: var(--tg-theme-button-color); +} + +.tweak-color__circle_header { + border: solid 1px var(--tg-theme-hint-color); + background-color: var(--tg-theme-header-bg-color); +} + +.tweak-color__circle_background { + border: solid 1px var(--tg-theme-hint-color); + background-color: var(--tg-theme-secondary-bg-color); +} + +.cloud-storage__table { + margin-bottom: 10px; +} + +.link__list { + color: var(--tg-theme-hint-color); + width: 88vw; +} + From 1bcb2a1d935527faead4e9c3dbea0935f7608443 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 11 Aug 2024 16:36:34 +0500 Subject: [PATCH 330/480] Revert "Use deepcopy for async" This reverts commit 74019d03afe7f0e0f4248c0cdf34655617256045. --- telebot/async_telebot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 27b861ead..d50cbf7e0 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -32,7 +32,7 @@ import string import random import ssl -import copy + """ Module : telebot @@ -558,7 +558,7 @@ async def _run_middlewares_and_handlers(self, message, handlers, middlewares, up logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function'])) return else: - data_copy = copy.deepcopy(data) + data_copy = data.copy() for key in list(data_copy): # remove data from data_copy if handler does not accept it if key not in params: From c79e63e3b300508f3e99b2ad841cc1889f9c6bc2 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 11 Aug 2024 16:36:41 +0500 Subject: [PATCH 331/480] Revert "Use deepcopy for sync" This reverts commit 2ae6b9308e05dff5632f2e6bf91301b74d5cb7fc. --- telebot/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 671c5631b..b154d04ca 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -20,7 +20,6 @@ # random module to generate random string import random import string -import copy import ssl @@ -8750,7 +8749,7 @@ def _run_middlewares_and_handler(self, message, handlers, middlewares, update_ty logger.error("It is not allowed to pass data and values inside data to the handler. Check your handler: {}".format(handler['function'])) return else: - data_copy = copy.deepcopy(data) + data_copy = data.copy() for key in list(data_copy): # remove data from data_copy if handler does not accept it if key not in params: From d44ebce95916f845b0493fdf395cd3f8b70ee1d0 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 11 Aug 2024 16:57:42 +0500 Subject: [PATCH 332/480] Fix versions --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- telebot/asyncio_storage/redis_storage.py | 2 +- telebot/storage/redis_storage.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index fc7f3cdc3..79db7c8d9 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6657,7 +6657,7 @@ def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[in Otherwise, if you only set user_id, chat_id will equal to user_id, this means that state will be set for the user in his private chat with a bot. - .. versionchanged:: 4.22.0 + .. versionchanged:: 4.23.0 Added additional parameters to support topics, business connections, and message threads. diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ec782ff91..92bf2e127 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7856,7 +7856,7 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Otherwise, if you only set user_id, chat_id will equal to user_id, this means that state will be set for the user in his private chat with a bot. - .. versionchanged:: 4.22.0 + .. versionchanged:: 4.23.0 Added additional parameters to support topics, business connections, and message threads. diff --git a/telebot/asyncio_storage/redis_storage.py b/telebot/asyncio_storage/redis_storage.py index eccff5c30..08e255809 100644 --- a/telebot/asyncio_storage/redis_storage.py +++ b/telebot/asyncio_storage/redis_storage.py @@ -297,7 +297,7 @@ def migrate_format(self, bot_id: int, prefix: Optional[str] = "telebot_"): Migrate from old to new format of keys. Run this function once to migrate all redis existing keys to new format. - Starting from version 4.22.0, the format of keys has been changed: + Starting from version 4.23.0, the format of keys has been changed: :value - Old format: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} - New format: diff --git a/telebot/storage/redis_storage.py b/telebot/storage/redis_storage.py index 19f5c2cd5..c9935ac5e 100644 --- a/telebot/storage/redis_storage.py +++ b/telebot/storage/redis_storage.py @@ -283,7 +283,7 @@ def migrate_format(self, bot_id: int, prefix: Optional[str] = "telebot_"): Migrate from old to new format of keys. Run this function once to migrate all redis existing keys to new format. - Starting from version 4.22.0, the format of keys has been changed: + Starting from version 4.23.0, the format of keys has been changed: :value - Old format: {prefix}chat_id: {user_id: {'state': None, 'data': {}}, ...} - New format: From 1540dd03832b4d35e81331d38cf00c18f2a65720 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 Aug 2024 11:59:22 +0000 Subject: [PATCH 333/480] Bump aiohttp from 3.9.4 to 3.10.2 Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.4 to 3.10.2. - [Release notes](https://github.com/aio-libs/aiohttp/releases) - [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst) - [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.4...v3.10.2) --- updated-dependencies: - dependency-name: aiohttp dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 09014549b..2abfd54bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest requests==2.32.0 wheel==0.38.1 -aiohttp==3.9.4 +aiohttp==3.10.2 From b198c3ab844585b1e327def2e374b96d92535baf Mon Sep 17 00:00:00 2001 From: nypava Date: Tue, 13 Aug 2024 15:15:57 +0300 Subject: [PATCH 334/480] async support & file renames --- examples/asynchronous_telebot/mini_app.py | 33 +++++++++++++++++++ examples/{webapp/bot.py => mini_app.py} | 4 ++- .../webapp => mini_app_web}/index.html | 2 +- .../{webapp/webapp => mini_app_web}/script.js | 2 +- .../{webapp/webapp => mini_app_web}/style.css | 0 5 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 examples/asynchronous_telebot/mini_app.py rename examples/{webapp/bot.py => mini_app.py} (82%) rename examples/{webapp/webapp => mini_app_web}/index.html (99%) rename examples/{webapp/webapp => mini_app_web}/script.js (99%) rename examples/{webapp/webapp => mini_app_web}/style.css (100%) diff --git a/examples/asynchronous_telebot/mini_app.py b/examples/asynchronous_telebot/mini_app.py new file mode 100644 index 000000000..3cdb811cb --- /dev/null +++ b/examples/asynchronous_telebot/mini_app.py @@ -0,0 +1,33 @@ +# The source of the "https://pytelegrambotminiapp.vercel.app" can be found in https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/mini_app_web + +import asyncio +from telebot.async_telebot import AsyncTeleBot +from telebot.types import ( + ReplyKeyboardMarkup, + KeyboardButton, + WebAppInfo, + InlineKeyboardMarkup, + InlineKeyboardButton +) + +BOT_TOKEN = "" +WEB_URL = "https://pytelegrambotminiapp.vercel.app" + +bot = AsyncTeleBot(BOT_TOKEN) + +@bot.message_handler(commands=["start"]) +async def start(message): + reply_keyboard_markup = ReplyKeyboardMarkup(resize_keyboard=True) + reply_keyboard_markup.row(KeyboardButton("Start MiniApp", web_app=WebAppInfo(WEB_URL))) + + inline_keyboard_markup = InlineKeyboardMarkup() + inline_keyboard_markup.row(InlineKeyboardButton('Start MiniApp', web_app=WebAppInfo(WEB_URL))) + + await bot.reply_to(message, "Click the bottom inline button to start MiniApp", reply_markup=inline_keyboard_markup) + await bot.reply_to(message, "Click keyboard button to start MiniApp", reply_markup=reply_keyboard_markup) + +@bot.message_handler(content_types=['web_app_data']) +async def web_app(message): + await bot.reply_to(message, f'Your message is "{message.web_app_data.data}"') + +asyncio.run(bot.polling()) diff --git a/examples/webapp/bot.py b/examples/mini_app.py similarity index 82% rename from examples/webapp/bot.py rename to examples/mini_app.py index 7fa106f09..735acd38c 100644 --- a/examples/webapp/bot.py +++ b/examples/mini_app.py @@ -1,3 +1,5 @@ +# The source of the "https://pytelegrambotminiapp.vercel.app" can be found in https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/mini_app_web + from telebot import TeleBot from telebot.types import ( ReplyKeyboardMarkup, @@ -8,7 +10,7 @@ ) BOT_TOKEN = "" -WEB_URL = "https://pytelegrambotminiapp.vercel.app" # https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/webapp/webapp +WEB_URL = "https://pytelegrambotminiapp.vercel.app" bot = TeleBot(BOT_TOKEN) diff --git a/examples/webapp/webapp/index.html b/examples/mini_app_web/index.html similarity index 99% rename from examples/webapp/webapp/index.html rename to examples/mini_app_web/index.html index 6f7d79ff7..22bd86ec9 100644 --- a/examples/webapp/webapp/index.html +++ b/examples/mini_app_web/index.html @@ -127,7 +127,7 @@

closing confirmation [Bot API 6.2+]

-

Confimation dialog when closing mini app

+

Confimation dialog when closing miniapp

diff --git a/examples/webapp/webapp/script.js b/examples/mini_app_web/script.js similarity index 99% rename from examples/webapp/webapp/script.js rename to examples/mini_app_web/script.js index 42889b055..4022ed5f0 100644 --- a/examples/webapp/webapp/script.js +++ b/examples/mini_app_web/script.js @@ -124,7 +124,7 @@ text.platform.innerText += telegram.platform; button.send_message.addEventListener('click', () => { telegram.sendData(input.message.value); - if (telegram.initDataUnsafe) telegram.showAlert('SendData only works in webapp that opened with reply keyboard.') + if (telegram.initDataUnsafe) telegram.showAlert('SendData only works in miniapp that opened with reply keyboard.') input.message.value = '' }); diff --git a/examples/webapp/webapp/style.css b/examples/mini_app_web/style.css similarity index 100% rename from examples/webapp/webapp/style.css rename to examples/mini_app_web/style.css From 407982da37415c9cc2f743679a6ca69c1959834f Mon Sep 17 00:00:00 2001 From: Badiboy Date: Thu, 15 Aug 2024 12:02:01 +0300 Subject: [PATCH 335/480] Bump version for intermediate release --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 1b8c80931..f6cdb5283 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.22.0' +release = '4.22.1' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index a45a8dd3b..20b08e9f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.22.0" +version = "4.22.1" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 3bbf77eb0..86d088045 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.22.0' +__version__ = '4.22.1' From 77c802c1ad7f82daeb1a40bd11cdd7787baf5cc2 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 14:57:57 +0500 Subject: [PATCH 336/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76f8f487e..1739e7595 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From 737e7e4e190acc7dfb2180493236359fe052bf80 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 14:58:12 +0500 Subject: [PATCH 337/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1739e7595..5f70cad2f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From 80cddf018e82570d31102d4782f32a471dbd6adf Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 15:05:28 +0500 Subject: [PATCH 338/480] Added the field paid_media to the class TransactionPartnerUser for transactions involving paid media. --- telebot/__init__.py | 8 ++++++-- telebot/apihelper.py | 5 ++++- telebot/async_telebot.py | 8 +++++--- telebot/asyncio_helper.py | 7 +++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 33a353de7..a84c6660d 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3136,7 +3136,8 @@ def send_paid_media( caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None) -> types.Message: + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, + ) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -3175,6 +3176,9 @@ def send_paid_media( :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3183,7 +3187,7 @@ def send_paid_media( self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, - reply_parameters=reply_parameters, reply_markup=reply_markup) + reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 2ee86abab..96a686b2e 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -529,7 +529,8 @@ def send_photo( def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, - disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None): + disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, + business_connection_id=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -549,6 +550,8 @@ def send_paid_media( payload['reply_parameters'] = reply_parameters.to_json() if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request( token, method_url, params=payload, method='post' if files else 'get', diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8647897b6..3cc008daf 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4564,7 +4564,7 @@ async def send_paid_media( caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None) -> types.Message: + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -4603,6 +4603,9 @@ async def send_paid_media( :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardMarkup` or :class:`telebot.types.ReplyKeyboardRemove` or :class:`telebot.types.ForceReply` + :param business_connection_id: Identifier of a business connection, in which the message will be sent + :type business_connection_id: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4611,8 +4614,7 @@ async def send_paid_media( self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, - reply_parameters=reply_parameters, reply_markup=reply_markup) - ) + reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id)) async def send_media_group( self, chat_id: Union[int, str], diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index fa14f6123..94af21eb8 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -309,7 +309,7 @@ async def send_message( if message_effect_id: params['message_effect_id'] = message_effect_id - return await _process_request(token, method_name, params=params) + return await _process_request(token, method_name, params=params, method='post') # methods @@ -519,7 +519,8 @@ async def send_photo( async def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, - disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None): + disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, + business_connection_id=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -539,6 +540,8 @@ async def send_paid_media( payload['reply_parameters'] = reply_parameters.to_json() if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request( token, method_url, params=payload, method='post' if files else 'get', From 496cc7c61ec377d572f2ca71756b6c029cfde00e Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 15:08:12 +0500 Subject: [PATCH 339/480] Added the field paid_media to the class TransactionPartnerUser for transactions involving paid media. --- telebot/types.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 21480e31d..ade17eb6e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10377,20 +10377,26 @@ class TransactionPartnerUser(TransactionPartner): :param invoice_payload: Optional, Bot-specified invoice payload :type invoice_payload: :obj:`str` + :param paid_media: Optional. Information about the paid media bought by the user + :type paid_media: :obj:`list` of :class:`PaidMedia` + :return: Instance of the class :rtype: :class:`TransactionPartnerUser` """ - def __init__(self, type, user, invoice_payload=None, **kwargs): + def __init__(self, type, user, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, **kwargs): self.type: str = type self.user: User = user self.invoice_payload: Optional[str] = invoice_payload + self.paid_media: Optional[List[PaidMedia]] = paid_media @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) + if 'paid_media' in obj: + obj['paid_media'] = [PaidMedia.de_json(media) for media in obj['paid_media']] return cls(**obj) class TransactionPartnerTelegramAds(TransactionPartner): From 80a5b94505d2bd6b6730eb99b8d876f66c3d6210 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 15:19:00 +0500 Subject: [PATCH 340/480] added 2 methods --- telebot/__init__.py | 56 ++++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 20 ++++++++++++++ telebot/async_telebot.py | 57 +++++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 22 +++++++++++++++ 4 files changed, 155 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index a84c6660d..658f70e58 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4199,6 +4199,62 @@ def edit_chat_invite_link( apihelper.edit_chat_invite_link(self.token, chat_id, invite_link, name, expire_date, member_limit, creates_join_request) ) + def create_chat_subscription_invite_link( + self, chat_id: Union[int, str], subscription_period: int, subscription_price: int, + name: Optional[str]=None) -> types.ChatInviteLink: + """ + Use this method to create a subscription invite link for a channel chat. The bot must have the can_invite_users administrator rights. + The link can be edited using the method editChatSubscriptionInviteLink or revoked using the method revokeChatInviteLink. + Returns the new invite link as a ChatInviteLink object. + + Telegram documentation: https://core.telegram.org/bots/api#createchatsubscriptioninvitelink + + :param chat_id: Unique identifier for the target channel chat or username of the target channel + (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param name: Invite link name; 0-32 characters + :type name: :obj:`str` + + :param subscription_period: The number of seconds the subscription will be active for before the next payment. + Currently, it must always be 2592000 (30 days). + :type subscription_period: :obj:`int` + + :param subscription_price: The amount of Telegram Stars a user must pay initially and after each subsequent + subscription period to be a member of the chat; 1-2500 + :type subscription_price: :obj:`int` + + :return: Returns the new invite link as a ChatInviteLink object. + :rtype: :class:`telebot.types.ChatInviteLink` + """ + return types.ChatInviteLink.de_json( + apihelper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name) + ) + + def edit_chat_subscription_invite_link( + self, chat_id: Union[int, str], invite_link: str, name: Optional[str]=None) -> types.ChatInviteLink: + """ + Use this method to edit a subscription invite link created by the bot. The bot must have the can_invite_users administrator rights. + Returns the edited invite link as a ChatInviteLink object. + + Telegram documentation: https://core.telegram.org/bots/api#editchatsubscriptioninvitelink + + :param chat_id: Unique identifier for the target chat or username of the target channel + (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param invite_link: The invite link to edit + :type invite_link: :obj:`str` + + :param name: Invite link name; 0-32 characters + :type name: :obj:`str` + + :return: Returns the edited invite link as a ChatInviteLink object. + :rtype: :class:`telebot.types.ChatInviteLink` + """ + return types.ChatInviteLink.de_json( + apihelper.edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name) + ) def revoke_chat_invite_link( self, chat_id: Union[int, str], invite_link: str) -> types.ChatInviteLink: diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 96a686b2e..495fa293d 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1205,6 +1205,26 @@ def edit_chat_invite_link(token, chat_id, invite_link, name, expire_date, member return _make_request(token, method_url, params=payload, method='post') +def create_chat_subscription_invite_link(token, chat_id, subscription_period, subscription_price, name=None): + method_url = 'createChatSubscriptionInviteLink' + payload = { + 'chat_id': chat_id, + 'subscription_period': subscription_period, + 'subscription_price': subscription_price + } + if name: + payload['name'] = name + return _make_request(token, method_url, params=payload, method='post') + +def edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name=None): + method_url = 'editChatSubscriptionInviteLink' + payload = { + 'chat_id': chat_id, + 'invite_link': invite_link + } + if name: + payload['name'] = name + return _make_request(token, method_url, params=payload, method='post') def revoke_chat_invite_link(token, chat_id, invite_link): method_url = 'revokeChatInviteLink' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 3cc008daf..5757a68bc 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5605,6 +5605,63 @@ async def edit_chat_invite_link( return types.ChatInviteLink.de_json( await asyncio_helper.edit_chat_invite_link(self.token, chat_id, invite_link, name, expire_date, member_limit, creates_join_request) ) + + async def create_chat_subscription_invite_link( + self, chat_id: Union[int, str], subscription_period: int, subscription_price: int, + name: Optional[str]=None) -> types.ChatInviteLink: + """ + Use this method to create a subscription invite link for a channel chat. The bot must have the can_invite_users administrator rights. + The link can be edited using the method editChatSubscriptionInviteLink or revoked using the method revokeChatInviteLink. + Returns the new invite link as a ChatInviteLink object. + + Telegram documentation: https://core.telegram.org/bots/api#createchatsubscriptioninvitelink + + :param chat_id: Unique identifier for the target channel chat or username of the target channel + (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param name: Invite link name; 0-32 characters + :type name: :obj:`str` + + :param subscription_period: The number of seconds the subscription will be active for before the next payment. + Currently, it must always be 2592000 (30 days). + :type subscription_period: :obj:`int` + + :param subscription_price: The amount of Telegram Stars a user must pay initially and after each subsequent + subscription period to be a member of the chat; 1-2500 + :type subscription_price: :obj:`int` + + :return: Returns the new invite link as a ChatInviteLink object. + :rtype: :class:`telebot.types.ChatInviteLink` + """ + return types.ChatInviteLink.de_json( + await asyncio_helper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name) + ) + + async def edit_chat_subscription_invite_link( + self, chat_id: Union[int, str], invite_link: str, name: Optional[str]=None) -> types.ChatInviteLink: + """ + Use this method to edit a subscription invite link created by the bot. The bot must have the can_invite_users administrator rights. + Returns the edited invite link as a ChatInviteLink object. + + Telegram documentation: https://core.telegram.org/bots/api#editchatsubscriptioninvitelink + + :param chat_id: Unique identifier for the target chat or username of the target channel + (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param invite_link: The invite link to edit + :type invite_link: :obj:`str` + + :param name: Invite link name; 0-32 characters + :type name: :obj:`str` + + :return: Returns the edited invite link as a ChatInviteLink object. + :rtype: :class:`telebot.types.ChatInviteLink` + """ + return types.ChatInviteLink.de_json( + await asyncio_helper.edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name) + ) async def revoke_chat_invite_link( self, chat_id: Union[int, str], invite_link: str) -> types.ChatInviteLink: diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 94af21eb8..c31bf53da 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1185,6 +1185,28 @@ async def edit_chat_invite_link(token, chat_id, invite_link, name, expire_date, return await _process_request(token, method_url, params=payload, method='post') +async def create_chat_subscription_invite_link(token, chat_id, subscription_period, subscription_price, name=None): + method_url = 'createChatSubscriptionInviteLink' + payload = { + 'chat_id': chat_id, + 'subscription_period': subscription_period, + 'subscription_price': subscription_price + } + if name: + payload['name'] = name + return await _process_request(token, method_url, params=payload, method='post') + +async def edit_chat_subscription_invite_link(token, chat_id, invite_link, name=None): + method_url = 'editChatSubscriptionInviteLink' + payload = { + 'chat_id': chat_id, + 'invite_link': invite_link + } + if name: + payload['name'] = name + return await _process_request(token, method_url, params=payload, method='post') + + async def revoke_chat_invite_link(token, chat_id, invite_link): method_url = 'revokeChatInviteLink' payload = { From d6216479b48fd029accdefed799fb4deb83be7eb Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 15:20:27 +0500 Subject: [PATCH 341/480] fix --- telebot/apihelper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 495fa293d..bc15e9316 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1216,7 +1216,7 @@ def create_chat_subscription_invite_link(token, chat_id, subscription_period, su payload['name'] = name return _make_request(token, method_url, params=payload, method='post') -def edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name=None): +def edit_chat_subscription_invite_link(token, chat_id, invite_link, name=None): method_url = 'editChatSubscriptionInviteLink' payload = { 'chat_id': chat_id, From 6c4599254422ef82925d7f1dfe46d751a2e6d356 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 15 Aug 2024 15:23:46 +0500 Subject: [PATCH 342/480] added reactiontypepaid --- telebot/types.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index ade17eb6e..1f85b14b5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8465,6 +8465,27 @@ def to_dict(self) -> dict: return json_dict +class ReactionTypePaid(ReactionType): + """ + This object represents a paid reaction type. + + Telegram documentation: https://core.telegram.org/bots/api#reactiontypepaid + + :param type: Type of the reaction, must be paid + :type type: :obj:`str` + + :return: Instance of the class + :rtype: :class:`ReactionTypePaid` + """ + + def __init__(self, **kwargs) -> None: + super().__init__('paid') + + def to_dict(self) -> dict: + return super().to_dict() + + + class MessageReactionUpdated(JsonDeserializable): """ This object represents a service message about a change in the list of the current user's reactions to a message. From b5f8fe8ea5583789ee6a91a8ecee28982d502a6b Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 16 Aug 2024 10:49:40 +0500 Subject: [PATCH 343/480] Fix states for webhooks --- telebot/asyncio_filters.py | 2 +- telebot/custom_filters.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index 20abe5464..77c0559a6 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -398,7 +398,7 @@ async def check(self, message, text): :meta private: """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot.bot_id) if chat_id is None: chat_id = user_id # May change in future diff --git a/telebot/custom_filters.py b/telebot/custom_filters.py index 2e91e55ea..f56535a57 100644 --- a/telebot/custom_filters.py +++ b/telebot/custom_filters.py @@ -404,7 +404,7 @@ def check(self, message, text): :meta private: """ - chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot._user.id) + chat_id, user_id, business_connection_id, bot_id, message_thread_id = resolve_context(message, self.bot.bot_id) if chat_id is None: chat_id = user_id # May change in future From 31a73ff14faec4b4158e204177bc1363a5060393 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Aug 2024 12:45:27 +0300 Subject: [PATCH 344/480] Fix some type hints and warnings --- telebot/types.py | 66 +++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 21480e31d..28ea9eca4 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1525,7 +1525,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.json = json_string @property - def html_text(self) -> str: + def html_text(self) -> Optional[str]: """ Returns html-rendered text. """ @@ -1534,7 +1534,7 @@ def html_text(self) -> str: return apply_html_entities(self.text, self.entities, getattr(self, "custom_subs", None)) @property - def html_caption(self) -> str: + def html_caption(self) -> Optional[str]: """ Returns html-rendered caption. """ @@ -2734,6 +2734,7 @@ def __init__(self, text: str, request_contact: Optional[bool]=None, if request_user is not None: logger.warning('The parameter "request_user" is deprecated, use "request_users" instead') if self.request_users is None: + # noinspection PyTypeChecker self.request_users = request_user @@ -4268,6 +4269,7 @@ def __init__(self, result_id, from_user, query, location=None, inline_message_id self.query: str = query +# noinspection PyShadowingBuiltins class InlineQueryResultBase(ABC, Dictionaryable, JsonSerializable): """ This object represents one result of an inline query. Telegram clients currently support results of the following 20 types: @@ -5407,8 +5409,8 @@ class InlineQueryResultCachedBase(ABC, JsonSerializable): Base class of all InlineQueryResultCached* classes. """ def __init__(self): - self.type: str = None - self.id: str = None + self.type: str = "" + self.id: str = "" self.title: Optional[str] = None self.description: Optional[str] = None self.caption: Optional[str] = None @@ -5416,6 +5418,7 @@ def __init__(self): self.input_message_content: Optional[InputMessageContent] = None self.parse_mode: Optional[str] = None self.caption_entities: Optional[List[MessageEntity]] = None + # noinspection PyTypeChecker self.payload_dic: Dict[str] = {} self.show_caption_above_media: Optional[bool] = None @@ -7104,6 +7107,7 @@ def to_dict(self): return json_dict +# noinspection PyShadowingBuiltins class Poll(JsonDeserializable): """ This object contains information about a poll. @@ -7586,7 +7590,7 @@ def to_dict(self): raise NotImplementedError -# noinspection PyUnusedLocal +# noinspection PyUnusedLocal,PyShadowingBuiltins class MenuButtonCommands(MenuButton): """ Represents a menu button, which opens the bot's list of commands. @@ -7610,7 +7614,7 @@ def to_json(self): return json.dumps(self.to_dict()) -# noinspection PyUnusedLocal +# noinspection PyUnusedLocal,PyShadowingBuiltins class MenuButtonWebApp(MenuButton): """ Represents a menu button, which launches a Web App. @@ -7645,7 +7649,7 @@ def to_json(self): return json.dumps(self.to_dict()) -# noinspection PyUnusedLocal +# noinspection PyUnusedLocal,PyShadowingBuiltins class MenuButtonDefault(MenuButton): """ Describes that no specific value for the menu button was set. @@ -8202,7 +8206,7 @@ def to_dict(self) -> dict: def to_json(self) -> str: return json.dumps(self.to_dict()) - def convert_input_sticker(self) -> Tuple[dict, Optional[dict]]: + def convert_input_sticker(self) -> Tuple[str, Optional[dict]]: if service_utils.is_string(self.sticker): return self.to_json(), None @@ -8343,6 +8347,7 @@ def to_json(self) -> str: return json.dumps(self.to_dict()) +# noinspection PyShadowingBuiltins class Story(JsonDeserializable): """ This object represents a story. @@ -9250,12 +9255,12 @@ def __init__(self, request_id: int, users: List[SharedUser], **kwargs): self.users: List[SharedUser] = users @property - def user_id(self) -> int: + def user_id(self) -> None: logger.warning('The parameter "user_id" is deprecated, use "user_ids" instead') return None @property - def user_ids(self) -> List[int]: + def user_ids(self) -> List[SharedUser]: logger.warning('The parameter "user_ids" is deprecated, use "users" instead') return self.users @@ -10217,8 +10222,9 @@ def de_json(cls, json_string): elif obj["type"] == "failed": return RevenueWithdrawalStateFailed.de_json(obj) return None - + +# noinspection PyShadowingBuiltins class RevenueWithdrawalStatePending(RevenueWithdrawalState): """ The withdrawal is in progress. @@ -10232,7 +10238,6 @@ class RevenueWithdrawalStatePending(RevenueWithdrawalState): :rtype: :class:`RevenueWithdrawalStatePending` """ - # noinspection PyPackageRequirements def __init__(self, type, **kwargs): self.type: str = type @@ -10243,6 +10248,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState): """ The withdrawal succeeded. @@ -10262,7 +10268,6 @@ class RevenueWithdrawalStateSucceeded(RevenueWithdrawalState): :rtype: :class:`RevenueWithdrawalStateSucceeded` """ - # noinspection PyPackageRequirements def __init__(self, type, date, url, **kwargs): self.type: str = type self.date: int = date @@ -10273,9 +10278,9 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - - + +# noinspection PyShadowingBuiltins class RevenueWithdrawalStateFailed(RevenueWithdrawalState): """ The withdrawal failed and the transaction was refunded. @@ -10289,7 +10294,6 @@ class RevenueWithdrawalStateFailed(RevenueWithdrawalState): :rtype: :class:`RevenueWithdrawalStateFailed` """ - # noinspection PyPackageRequirements def __init__(self, type, **kwargs): self.type: str = type @@ -10329,7 +10333,9 @@ def de_json(cls, json_string): return TransactionPartnerTelegramAds.de_json(obj) elif obj["type"] == "other": return TransactionPartnerOther.de_json(obj) - + + +# noinspection PyShadowingBuiltins class TransactionPartnerFragment(TransactionPartner): """ Describes a withdrawal transaction with Fragment. @@ -10347,7 +10353,6 @@ class TransactionPartnerFragment(TransactionPartner): """ - # noinspection PyPackageRequirements def __init__(self, type, withdrawal_state=None, **kwargs): self.type: str = type self.withdrawal_state: Optional[RevenueWithdrawalState] = withdrawal_state @@ -10359,9 +10364,9 @@ def de_json(cls, json_string): if 'withdrawal_state' in obj: obj['withdrawal_state'] = RevenueWithdrawalState.de_json(obj['withdrawal_state']) return cls(**obj) - +# noinspection PyShadowingBuiltins class TransactionPartnerUser(TransactionPartner): """ Describes a transaction with a user. @@ -10392,7 +10397,9 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) return cls(**obj) - + + +# noinspection PyShadowingBuiltins class TransactionPartnerTelegramAds(TransactionPartner): """ Describes a transaction with Telegram Ads. @@ -10413,8 +10420,10 @@ def __init__(self, type, **kwargs): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - - + return obj + + +# noinspection PyShadowingBuiltins class TransactionPartnerOther(TransactionPartner): """ Describes a transaction with an unknown source or recipient. @@ -10436,9 +10445,9 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - +# noinspection PyShadowingBuiltins class StarTransaction(JsonDeserializable): """ Describes a Telegram Star transaction. @@ -10531,7 +10540,9 @@ def de_json(cls, json_string): return PaidMediaPhoto.de_json(obj) elif obj["type"] == "video": return PaidMediaVideo.de_json(obj) - + + +# noinspection PyShadowingBuiltins class PaidMediaPreview(PaidMedia): """ The paid media isn't available before the payment. @@ -10565,8 +10576,9 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + +# noinspection PyShadowingBuiltins class PaidMediaPhoto(PaidMedia): """ The paid media is a photo. @@ -10595,8 +10607,9 @@ def de_json(cls, json_string): obj['photo'] = [PhotoSize.de_json(photo) for photo in obj['photo']] return cls(**obj) - + +# noinspection PyShadowingBuiltins class PaidMediaVideo(PaidMedia): """ The paid media is a video. @@ -10653,6 +10666,7 @@ def __init__(self, star_count, paid_media, **kwargs): self.paid_media: List[PaidMedia] = paid_media +# noinspection PyShadowingBuiltins class InputPaidMedia(JsonSerializable): """ This object describes the paid media to be sent. Currently, it can be one of From 2d41d2a516ed5cf513d5ab7ae30a67f32c9a55d7 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Aug 2024 13:23:07 +0300 Subject: [PATCH 345/480] any_text / any_entities to Message --- telebot/types.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 28ea9eca4..e972696b1 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1618,6 +1618,14 @@ def user_shared(self): logger.warning('The parameter "user_shared" is deprecated, use "users_shared" instead') return self.users_shared + @property + def any_text(self): + return self.caption if (self.caption is not None) else self.text + + @property + def any_entities(self): + return self.caption_entities if (self.caption_entities is not None) else self.entities + # noinspection PyShadowingBuiltins class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): From 8dcfdc5e6bfb5d5633c8c55e1ac3f84030526140 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Aug 2024 19:08:25 +0300 Subject: [PATCH 346/480] any_xxx typehints added --- telebot/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index e972696b1..badd99a75 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1619,11 +1619,11 @@ def user_shared(self): return self.users_shared @property - def any_text(self): + def any_text(self) -> Optional[str]: return self.caption if (self.caption is not None) else self.text @property - def any_entities(self): + def any_entities(self) -> Optional[List[MessageEntity]]: return self.caption_entities if (self.caption_entities is not None) else self.entities From 25266a17a624f1e40f448fc7c2626f8f79fc4390 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 17 Aug 2024 22:36:58 +0500 Subject: [PATCH 347/480] use named parameters for creating and editing chat subcription links --- telebot/__init__.py | 4 ++-- telebot/async_telebot.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 658f70e58..bddcda75b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4228,7 +4228,7 @@ def create_chat_subscription_invite_link( :rtype: :class:`telebot.types.ChatInviteLink` """ return types.ChatInviteLink.de_json( - apihelper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name) + apihelper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name=name) ) def edit_chat_subscription_invite_link( @@ -4253,7 +4253,7 @@ def edit_chat_subscription_invite_link( :rtype: :class:`telebot.types.ChatInviteLink` """ return types.ChatInviteLink.de_json( - apihelper.edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name) + apihelper.edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name=name) ) def revoke_chat_invite_link( diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 5757a68bc..e2b77b0e6 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5635,7 +5635,7 @@ async def create_chat_subscription_invite_link( :rtype: :class:`telebot.types.ChatInviteLink` """ return types.ChatInviteLink.de_json( - await asyncio_helper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name) + await asyncio_helper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name=name) ) async def edit_chat_subscription_invite_link( @@ -5660,7 +5660,7 @@ async def edit_chat_subscription_invite_link( :rtype: :class:`telebot.types.ChatInviteLink` """ return types.ChatInviteLink.de_json( - await asyncio_helper.edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name) + await asyncio_helper.edit_chat_subscription_invite_link(self.token, chat_id, invite_link, name=name) ) async def revoke_chat_invite_link( From dd30e78dd45c53165f579d089c5cb9e76d213a27 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 17 Aug 2024 22:46:45 +0300 Subject: [PATCH 348/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f6cdb5283..87d25810f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.22.1' +release = '4.23.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 72f0a2962..07f2ce727 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.22.1" +version = "4.23.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 86d088045..bf02d6515 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.22.1' +__version__ = '4.23.0' From 85c471970e1b722a55fb36a417471f9047077016 Mon Sep 17 00:00:00 2001 From: GautamKumar Date: Wed, 21 Aug 2024 02:56:27 +0530 Subject: [PATCH 349/480] Fix: Correct order of parameters in forward_messages --- telebot/async_telebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index e2b77b0e6..fcb0df2d1 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3439,7 +3439,7 @@ async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[s disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, protect_content, message_thread_id) + result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, protect_content) return [types.MessageID.de_json(message_id) for message_id in result] async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], From 60d830391ffb80a8df754651a98c6f9dee834542 Mon Sep 17 00:00:00 2001 From: Emil Relecto Date: Wed, 21 Aug 2024 14:09:56 +0200 Subject: [PATCH 350/480] set answer_pre_checkout_query query_id argument type to str As per the documentation - https://core.telegram.org/bots/api#answerprecheckoutquery --- telebot/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index bddcda75b..95b6cca46 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5627,7 +5627,7 @@ def answer_shipping_query( def answer_pre_checkout_query( - self, pre_checkout_query_id: int, ok: bool, + self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str]=None) -> bool: """ Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the From 99d3243ee13156d53b96327e29fcba1a9d51f320 Mon Sep 17 00:00:00 2001 From: Emil Relecto Date: Wed, 21 Aug 2024 14:16:00 +0200 Subject: [PATCH 351/480] set answer_pre_checkout_query query id type to string. in async_telebot.py --- telebot/async_telebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index fcb0df2d1..4a71772a4 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6977,7 +6977,7 @@ async def answer_shipping_query( return await asyncio_helper.answer_shipping_query(self.token, shipping_query_id, ok, shipping_options, error_message) async def answer_pre_checkout_query( - self, pre_checkout_query_id: int, ok: bool, + self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str]=None) -> bool: """ Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the From 377636774d7d5eaa1d5b49ebbd094c2d96361103 Mon Sep 17 00:00:00 2001 From: pnwclw <45664035+pnwclw@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:38:59 +0200 Subject: [PATCH 352/480] Fixed typing for `request_name` parameter --- telebot/types.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 70907aa1f..8b4c30469 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2561,13 +2561,13 @@ class KeyboardButtonRequestUsers(Dictionaryable): """ def __init__( self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, - max_quantity: Optional[int]=None, request_name: Optional[str]=None, request_username: Optional[bool]=None, + max_quantity: Optional[int]=None, request_name: Optional[bool]=None, request_username: Optional[bool]=None, request_photo: Optional[bool]=None) -> None: self.request_id: int = request_id self.user_is_bot: Optional[bool] = user_is_bot self.user_is_premium: Optional[bool] = user_is_premium self.max_quantity: Optional[int] = max_quantity - self.request_name: Optional[str] = request_name + self.request_name: Optional[bool] = request_name self.request_username: Optional[bool] = request_username self.request_photo: Optional[bool] = request_photo @@ -10856,4 +10856,4 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - \ No newline at end of file + From 6ebe88dd310fd22a526044d3e207a3017737623f Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 6 Sep 2024 17:58:05 +0400 Subject: [PATCH 353/480] added purchased paid media --- telebot/__init__.py | 66 +++++++++++++++++++++++++++++++++++++--- telebot/async_telebot.py | 63 ++++++++++++++++++++++++++++++++++++++ telebot/types.py | 36 ++++++++++++++++++++-- 3 files changed, 159 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 95b6cca46..a7071438e 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -248,6 +248,7 @@ def __init__( self.business_message_handlers = [] self.edited_business_message_handlers = [] self.deleted_business_messages_handlers = [] + self.purchased_paid_media_handlers = [] self.custom_filters = {} self.state_handlers = [] @@ -724,6 +725,7 @@ def process_new_updates(self, updates: List[types.Update]): new_business_messages = None new_edited_business_messages = None new_deleted_business_messages = None + new_purchased_paid_media = None for update in updates: if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares: @@ -805,8 +807,10 @@ def process_new_updates(self, updates: List[types.Update]): if update.deleted_business_messages: if new_deleted_business_messages is None: new_deleted_business_messages = [] new_deleted_business_messages.append(update.deleted_business_messages) - - + if update.purchased_paid_media: + if new_purchased_paid_media is None: new_purchased_paid_media = [] + new_purchased_paid_media.append(update.purchased_paid_media) + if new_messages: self.process_new_messages(new_messages) if new_edited_messages: @@ -851,6 +855,8 @@ def process_new_updates(self, updates: List[types.Update]): self.process_new_edited_business_message(new_edited_business_messages) if new_deleted_business_messages: self.process_new_deleted_business_messages(new_deleted_business_messages) + if new_purchased_paid_media: + self.process_new_purchased_paid_media(new_purchased_paid_media) def process_new_messages(self, new_messages): """ @@ -987,8 +993,11 @@ def process_new_deleted_business_messages(self, new_deleted_business_messages): """ self._notify_command_handlers(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages') - - + def process_new_purchased_paid_media(self, new_purchased_paid_media): + """ + :meta private: + """ + self._notify_command_handlers(self.purchased_paid_media_handlers, new_purchased_paid_media, 'purchased_paid_media') def process_middlewares(self, update): """ @@ -8035,6 +8044,55 @@ def register_pre_checkout_query_handler(self, callback: Callable, func: Callable handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_pre_checkout_query_handler(handler_dict) + def purchased_paid_media_handler(self, func=None, **kwargs): + """ + Handles new incoming purchased paid media. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_purchased_paid_media_handler(handler_dict) + return handler + + return decorator + + def add_purchased_paid_media_handler(self, handler_dict): + """ + Adds a purchased paid media handler + Note that you should use register_purchased_paid_media_handler to add purchased_paid_media_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.purchased_paid_media_handlers.append(handler_dict) + + def register_purchased_paid_media_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers purchased paid media handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_purchased_paid_media_handler(handler_dict) def poll_handler(self, func, **kwargs): """ diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 4a71772a4..eff7fb931 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -183,6 +183,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ self.business_message_handlers = [] self.edited_business_message_handlers = [] self.deleted_business_messages_handlers = [] + self.purchased_paid_media_handlers = [] self.custom_filters = {} self.state_handlers = [] @@ -636,6 +637,7 @@ async def process_new_updates(self, updates: List[types.Update]): new_business_messages = None new_edited_business_messages = None new_deleted_business_messages = None + new_purchased_paid_media = None for update in updates: @@ -706,6 +708,9 @@ async def process_new_updates(self, updates: List[types.Update]): if update.deleted_business_messages: if new_deleted_business_messages is None: new_deleted_business_messages = [] new_deleted_business_messages.append(update.deleted_business_messages) + if update.purchased_paid_media: + if new_purchased_paid_media is None: new_purchased_paid_media = [] + new_purchased_paid_media.append(update.purchased_paid_media) if new_messages: @@ -750,6 +755,8 @@ async def process_new_updates(self, updates: List[types.Update]): await self.process_new_edited_business_message(new_edited_business_messages) if new_deleted_business_messages: await self.process_new_deleted_business_messages(new_deleted_business_messages) + if new_purchased_paid_media: + await self.process_new_purchased_paid_media(new_purchased_paid_media) async def process_new_messages(self, new_messages): """ @@ -884,6 +891,12 @@ async def process_new_deleted_business_messages(self, new_deleted_business_messa """ await self._process_updates(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages') + async def process_new_purchased_paid_media(self, new_purchased_paid_media): + """ + :meta private: + """ + await self._process_updates(self.purchased_paid_media_handlers, new_purchased_paid_media, 'purchased_paid_media') + async def _get_middlewares(self, update_type): """ :meta private: @@ -1867,6 +1880,56 @@ def register_pre_checkout_query_handler(self, callback: Callable[[Any], Awaitabl handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) self.add_pre_checkout_query_handler(handler_dict) + def purchased_paid_media_handler(self, func=None, **kwargs): + """ + Handles new incoming purchased paid media. + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_purchased_paid_media_handler(handler_dict) + return handler + + return decorator + + def add_purchased_paid_media_handler(self, handler_dict): + """ + Adds a purchased paid media handler + Note that you should use register_purchased_paid_media_handler to add purchased_paid_media_handler to the bot. + + :meta private: + + :param handler_dict: + :return: + """ + self.purchased_paid_media_handlers.append(handler_dict) + + def register_purchased_paid_media_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): + """ + Registers purchased paid media handler. + + :param callback: function to be called + :type callback: :obj:`function` + + :param func: Function executed as a filter + :type func: :obj:`function` + + :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) + :type pass_bot: :obj:`bool` + + :param kwargs: Optional keyword arguments(custom filters) + + :return: None + """ + handler_dict = self._build_handler_dict(callback, func=func, pass_bot=pass_bot, **kwargs) + self.add_purchased_paid_media_handler(handler_dict) + def poll_handler(self, func, **kwargs): """ Handles new state of a poll. Bots receive only updates about stopped polls and polls, which are sent by the bot diff --git a/telebot/types.py b/telebot/types.py index 8b4c30469..df2959e6a 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -153,6 +153,9 @@ class Update(JsonDeserializable): checkout :type pre_checkout_query: :class:`telebot.types.PreCheckoutQuery` + :purchased_paid_media: Optional. A user purchased paid media with a non-empty payload sent by the bot in a non-channel chat + :type purchased_paid_media: :class:`telebot.types.PaidMediaPurchased` + :param poll: Optional. New poll state. Bots receive only updates about stopped polls and polls, which are sent by the bot :type poll: :class:`telebot.types.Poll` @@ -222,18 +225,19 @@ def de_json(cls, json_string): business_message = Message.de_json(obj.get('business_message')) edited_business_message = Message.de_json(obj.get('edited_business_message')) deleted_business_messages = BusinessMessagesDeleted.de_json(obj.get('deleted_business_messages')) + purchased_paid_media = PaidMediaPurchased.de_json(obj.get('purchased_paid_media')) return cls(update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, business_connection, business_message, edited_business_message, - deleted_business_messages) + deleted_business_messages, purchased_paid_media) def __init__(self, update_id, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, removed_chat_boost, chat_boost, business_connection, business_message, edited_business_message, - deleted_business_messages, **kwargs): + deleted_business_messages, purchased_paid_media): self.update_id: int = update_id self.message: Optional[Message] = message self.edited_message: Optional[Message] = edited_message @@ -257,6 +261,7 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.business_message: Optional[Message] = business_message self.edited_business_message: Optional[Message] = edited_business_message self.deleted_business_messages: Optional[BusinessMessagesDeleted] = deleted_business_messages + self.purchased_paid_media: Optional[PaidMediaPurchased] = purchased_paid_media @@ -10857,3 +10862,30 @@ def de_json(cls, json_string): return cls(**obj) +class PaidMediaPurchased(JsonDeserializable): + """ + This object contains information about a paid media purchase. + + Telegram documentation: https://core.telegram.org/bots/api#paidmediapurchased + + :param from_user: User who purchased the media + :type from_user: :class:`User` + + :param paid_media_payload: Bot-specified paid media payload + :type paid_media_payload: :obj:`str` + + :return: Instance of the class + :rtype: :class:`PaidMediaPurchased` + """ + + def __init__(self, from_user, paid_media_payload, **kwargs): + self.from_user: User = from_user + self.paid_media_payload: str = paid_media_payload + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['from_user'] = User.de_json(obj['from_user']) + return cls(**obj) + From e3081fb62d4db8d5fa8cb4ec468b0e6a361309d5 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 6 Sep 2024 18:04:57 +0400 Subject: [PATCH 354/480] added payload to sendpaidmedia --- telebot/__init__.py | 7 ++++++- telebot/apihelper.py | 4 +++- telebot/async_telebot.py | 9 +++++++-- telebot/asyncio_helper.py | 5 ++++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index a7071438e..6a874ea9e 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3146,6 +3146,7 @@ def send_paid_media( show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, + payload: Optional[str]=None ) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -3188,6 +3189,9 @@ def send_paid_media( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes. + :type payload: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3196,7 +3200,8 @@ def send_paid_media( self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, - reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id) + reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, + media_payload=payload) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index bc15e9316..1f553deef 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -530,7 +530,7 @@ def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None): + business_connection_id=None, media_payload=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -552,6 +552,8 @@ def send_paid_media( payload['reply_markup'] = _convert_markup(reply_markup) if business_connection_id: payload['business_connection_id'] = business_connection_id + if media_payload: + payload['payload'] = media_payload return _make_request( token, method_url, params=payload, method='post' if files else 'get', diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index eff7fb931..dd44c2417 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4627,7 +4627,8 @@ async def send_paid_media( caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None) -> types.Message: + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, + payload: Optional[str]=None) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -4669,6 +4670,9 @@ async def send_paid_media( :param business_connection_id: Identifier of a business connection, in which the message will be sent :type business_connection_id: :obj:`str` + :param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes. + :type payload: :obj:`str` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4677,7 +4681,8 @@ async def send_paid_media( self.token, chat_id, star_count, media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, - reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id)) + reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, + media_payload=payload)) async def send_media_group( self, chat_id: Union[int, str], diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index c31bf53da..f4c27d71f 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -520,7 +520,7 @@ async def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None): + business_connection_id=None, media_payload=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -542,6 +542,9 @@ async def send_paid_media( payload['reply_markup'] = _convert_markup(reply_markup) if business_connection_id: payload['business_connection_id'] = business_connection_id + if media_payload: + payload['payload'] = media_payload + return await _process_request( token, method_url, params=payload, method='post' if files else 'get', From 155608e58b5959df8df03a1dd7d4262e95640081 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 6 Sep 2024 20:32:23 +0400 Subject: [PATCH 355/480] prize_star_count and everything related to star giveaways --- telebot/types.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index df2959e6a..0aa302012 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8994,6 +8994,9 @@ class Giveaway(JsonDeserializable): :param country_codes: Optional. A list of two-letter ISO 3166-1 alpha-2 country codes indicating the countries from which eligible users for the giveaway must come. If empty, then all users can participate in the giveaway. :type country_codes: :obj:`list` of :obj:`str` + :param prize_star_count: Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + :type prize_star_count: :obj:`int` + :param premium_subscription_month_count: Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for :type premium_subscription_month_count: :obj:`int` @@ -9011,7 +9014,7 @@ def de_json(cls, json_string): def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: int, only_new_members: Optional[bool] = None, has_public_winners: Optional[bool] = None, prize_description: Optional[str] = None, country_codes: Optional[List[str]] = None, - premium_subscription_month_count: Optional[int] = None, **kwargs) -> None: + premium_subscription_month_count: Optional[int] = None, prize_star_count: Optional[int] = None, **kwargs) -> None: self.chats: List[Chat] = chats self.winners_selection_date: int = winners_selection_date self.winner_count: int = winner_count @@ -9020,6 +9023,7 @@ def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: self.prize_description: Optional[str] = prize_description self.country_codes: Optional[List[str]] = country_codes self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count + self.prize_star_count: Optional[int] = prize_star_count class GiveawayWinners(JsonDeserializable): @@ -9061,6 +9065,9 @@ class GiveawayWinners(JsonDeserializable): :param prize_description: Optional. Description of additional giveaway prize :type prize_description: :obj:`str` + :param prize_star_count: Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + :type prize_star_count: :obj:`int` + :return: Instance of the class :rtype: :class:`GiveawayWinners` """ @@ -9077,7 +9084,7 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: winners: List[User], additional_chat_count: Optional[int] = None, premium_subscription_month_count: Optional[int] = None, unclaimed_prize_count: Optional[int] = None, only_new_members: Optional[bool] = None, was_refunded: Optional[bool] = None, - prize_description: Optional[str] = None, **kwargs) -> None: + prize_description: Optional[str] = None, prize_star_count: Optional[int] = None, **kwargs) -> None: self.chat: Chat = chat self.giveaway_message_id: int = giveaway_message_id self.winners_selection_date: int = winners_selection_date @@ -9089,6 +9096,7 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: self.only_new_members: Optional[bool] = only_new_members self.was_refunded: Optional[bool] = was_refunded self.prize_description: Optional[str] = prize_description + self.prize_star_count: Optional[int] = prize_star_count class GiveawayCompleted(JsonDeserializable): @@ -9106,6 +9114,9 @@ class GiveawayCompleted(JsonDeserializable): :param giveaway_message: Optional. Message with the giveaway that was completed, if it wasn't deleted :type giveaway_message: :class:`Message` + :param is_star_giveaway: Optional. True, if the giveaway was a Telegram Star giveaway + :type is_star_giveaway: :obj:`bool` + :return: Instance of the class :rtype: :class:`GiveawayCompleted` """ @@ -9119,15 +9130,21 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = None, - giveaway_message: Optional[Message] = None, **kwargs) -> None: + giveaway_message: Optional[Message] = None, is_star_giveaway: Optional[bool] = None, **kwargs) -> None: self.winner_count: int = winner_count self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count self.giveaway_message: Optional[Message] = giveaway_message + self.is_star_giveaway: Optional[bool] = is_star_giveaway class GiveawayCreated(JsonDeserializable): """ - This object represents a service message about the creation of a scheduled giveaway. Currently holds no information. + This object represents a service message about the creation of a scheduled giveaway. + + :prize_star_count: Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + :type prize_star_count: :obj:`int` + + :return: Instance of the class """ @classmethod @@ -9136,8 +9153,8 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, **kwargs) -> None: - pass + def __init__(self, prize_star_count=None, **kwargs) -> None: + self.prize_star_count: Optional[str] = prize_star_count class TextQuote(JsonDeserializable): @@ -9468,6 +9485,9 @@ class ChatBoostSourceGiveaway(ChatBoostSource): :param is_unclaimed: True, if the giveaway was completed, but there was no user to win the prize :type is_unclaimed: :obj:`bool` + :param prize_star_count: Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + :type prize_star_count: :obj:`int` + :return: Instance of the class :rtype: :class:`ChatBoostSourceGiveaway` """ @@ -9479,11 +9499,12 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj.get('user')) return cls(**obj) - def __init__(self, source, giveaway_message_id, user=None, is_unclaimed=None, **kwargs): + def __init__(self, source, giveaway_message_id, user=None, is_unclaimed=None, prize_star_count=None, **kwargs): self.source: str = source self.giveaway_message_id: int = giveaway_message_id self.user: User = user self.is_unclaimed: bool = is_unclaimed + self.prize_star_count: Optional[int] = prize_star_count class ChatBoost(JsonDeserializable): From ad70e7f0e11f3ca7a59d31df4a1593a80aa6dcdb Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 6 Sep 2024 20:35:53 +0400 Subject: [PATCH 356/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f70cad2f..1959744fa 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From f116f925a432544d7a6d2ba3bbb5dc2fac9fce6d Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 6 Sep 2024 20:44:26 +0400 Subject: [PATCH 357/480] fix tests --- tests/test_handler_backends.py | 4 ++-- tests/test_telebot.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test_handler_backends.py b/tests/test_handler_backends.py index b74d6fad0..4df760ebc 100644 --- a/tests/test_handler_backends.py +++ b/tests/test_handler_backends.py @@ -71,7 +71,7 @@ def update_type(message): chat_boost_removed = None return types.Update(1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, None, None, None, None) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, None, None, None, None, None) @pytest.fixture() @@ -95,7 +95,7 @@ def reply_to_message_update_type(reply_to_message): chat_boost_removed = None return types.Update(1001234038284, reply_to_message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, - poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, None, None, None, None) + poll, poll_answer, my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, None, None, None, None, None) def next_handler(message): diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 52adbc2fe..8b04ac402 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -546,9 +546,11 @@ def create_message_update(text): message_reaction_count = None chat_boost = None chat_boost_removed = None + purchased_paid_media = None return types.Update(-1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed) + my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, + purchased_paid_media) def test_is_string_unicode(self): s1 = u'string' From 3759a95218875fdc7a3cae7626a4e8f730ef0811 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 16 Sep 2024 20:34:30 +0400 Subject: [PATCH 358/480] Fixes from review --- telebot/__init__.py | 2 +- telebot/apihelper.py | 28 ++++++++++++++-------------- telebot/async_telebot.py | 2 +- telebot/asyncio_helper.py | 29 +++++++++++++++-------------- telebot/types.py | 4 ++-- telebot/util.py | 2 +- 6 files changed, 34 insertions(+), 33 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 6a874ea9e..a79c2ea50 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3201,7 +3201,7 @@ def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - media_payload=payload) + payload=payload) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 1f553deef..c46b108c8 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -530,32 +530,32 @@ def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, media_payload=None): + business_connection_id=None, payload=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) - payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} + _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} if caption: - payload['caption'] = caption + _payload['caption'] = caption if parse_mode: - payload['parse_mode'] = parse_mode + _payload['parse_mode'] = parse_mode if caption_entities: - payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + _payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if show_caption_above_media is not None: - payload['show_caption_above_media'] = show_caption_above_media + _payload['show_caption_above_media'] = show_caption_above_media if disable_notification is not None: - payload['disable_notification'] = disable_notification + _payload['disable_notification'] = disable_notification if protect_content is not None: - payload['protect_content'] = protect_content + _payload['protect_content'] = protect_content if reply_parameters is not None: - payload['reply_parameters'] = reply_parameters.to_json() + _payload['reply_parameters'] = reply_parameters.to_json() if reply_markup: - payload['reply_markup'] = _convert_markup(reply_markup) + _payload['reply_markup'] = _convert_markup(reply_markup) if business_connection_id: - payload['business_connection_id'] = business_connection_id - if media_payload: - payload['payload'] = media_payload + _payload['business_connection_id'] = business_connection_id + if payload: + _payload['payload'] = payload return _make_request( - token, method_url, params=payload, + token, method_url, params=_payload, method='post' if files else 'get', files=files if files else None) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index dd44c2417..ef35d109a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4682,7 +4682,7 @@ async def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - media_payload=payload)) + payload=payload)) async def send_media_group( self, chat_id: Union[int, str], diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index f4c27d71f..0bd447f18 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -520,33 +520,34 @@ async def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, media_payload=None): + business_connection_id=None, payload=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) - payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} + _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} + # USE _payload for request payload if caption: - payload['caption'] = caption + _payload['caption'] = caption if parse_mode: - payload['parse_mode'] = parse_mode + _payload['parse_mode'] = parse_mode if caption_entities: - payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + _payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if show_caption_above_media is not None: - payload['show_caption_above_media'] = show_caption_above_media + _payload['show_caption_above_media'] = show_caption_above_media if disable_notification is not None: - payload['disable_notification'] = disable_notification + _payload['disable_notification'] = disable_notification if protect_content is not None: - payload['protect_content'] = protect_content + _payload['protect_content'] = protect_content if reply_parameters is not None: - payload['reply_parameters'] = reply_parameters.to_json() + _payload['reply_parameters'] = reply_parameters.to_json() if reply_markup: - payload['reply_markup'] = _convert_markup(reply_markup) + _payload['reply_markup'] = _convert_markup(reply_markup) if business_connection_id: - payload['business_connection_id'] = business_connection_id - if media_payload: - payload['payload'] = media_payload + _payload['business_connection_id'] = business_connection_id + if payload: + _payload['payload'] = payload return await _process_request( - token, method_url, params=payload, + token, method_url, params=_payload, method='post' if files else 'get', files=files if files else None) diff --git a/telebot/types.py b/telebot/types.py index 0aa302012..043473aee 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9502,8 +9502,8 @@ def de_json(cls, json_string): def __init__(self, source, giveaway_message_id, user=None, is_unclaimed=None, prize_star_count=None, **kwargs): self.source: str = source self.giveaway_message_id: int = giveaway_message_id - self.user: User = user - self.is_unclaimed: bool = is_unclaimed + self.user: Optional[User] = user + self.is_unclaimed: Optional[bool] = is_unclaimed self.prize_star_count: Optional[int] = prize_star_count diff --git a/telebot/util.py b/telebot/util.py index 0448893e1..bed0e8c19 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -48,7 +48,7 @@ "message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member", "chat_join_request", "message_reaction", "message_reaction_count", "chat_boost", "removed_chat_boost", - "business_connection", "business_message", "edited_business_message", "deleted_business_messages" + "business_connection", "business_message", "edited_business_message", "deleted_business_messages", "purchased_paid_media" ] From ce0c525973244fb21358c374a3f739fb04964925 Mon Sep 17 00:00:00 2001 From: uak <4626956-uak@users.noreply.gitlab.com> Date: Mon, 30 Sep 2024 08:55:39 +0300 Subject: [PATCH 359/480] Replaced depreicated reply_to_message_id --- examples/asynchronous_telebot/custom_states.py | 17 ++++++++++------- examples/custom_states.py | 17 ++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/examples/asynchronous_telebot/custom_states.py b/examples/asynchronous_telebot/custom_states.py index f0111e27e..f3437660f 100644 --- a/examples/asynchronous_telebot/custom_states.py +++ b/examples/asynchronous_telebot/custom_states.py @@ -2,6 +2,7 @@ from telebot.asyncio_storage import StateMemoryStorage from telebot.states import State, StatesGroup from telebot.states.asyncio.context import StateContext +from telebot.types import ReplyParameters # Initialize the bot state_storage = StateMemoryStorage() # don't use this in production; switch to redis @@ -23,7 +24,7 @@ async def start_ex(message: types.Message, state: StateContext): await bot.send_message( message.chat.id, "Hello! What is your first name?", - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -34,7 +35,7 @@ async def any_state(message: types.Message, state: StateContext): await bot.send_message( message.chat.id, "Your information has been cleared. Type /start to begin again.", - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -43,7 +44,8 @@ async def any_state(message: types.Message, state: StateContext): async def name_get(message: types.Message, state: StateContext): await state.set(MyStates.age) await bot.send_message( - message.chat.id, "How old are you?", reply_to_message_id=message.message_id + message.chat.id, "How old are you?", + reply_parameters=ReplyParameters(message_id=message.message_id), ) await state.add_data(name=message.text) @@ -64,7 +66,7 @@ async def ask_color(message: types.Message, state: StateContext): message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -84,7 +86,7 @@ async def ask_hobby(message: types.Message, state: StateContext): message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -123,7 +125,8 @@ async def finish(message: types.Message, state: StateContext): ) await bot.send_message( - message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id + message.chat.id, msg, parse_mode="html", + reply_parameters=ReplyParameters(message_id=message.message_id), ) await state.delete() @@ -134,7 +137,7 @@ async def age_incorrect(message: types.Message): await bot.send_message( message.chat.id, "Please enter a valid number for age.", - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) diff --git a/examples/custom_states.py b/examples/custom_states.py index 131dd1d42..e1bf13295 100644 --- a/examples/custom_states.py +++ b/examples/custom_states.py @@ -3,6 +3,7 @@ from telebot.states import State, StatesGroup from telebot.states.sync.context import StateContext from telebot.storage import StateMemoryStorage +from telebot.types import ReplyParameters # Initialize the bot state_storage = StateMemoryStorage() # don't use this in production; switch to redis @@ -24,7 +25,7 @@ def start_ex(message: types.Message, state: StateContext): bot.send_message( message.chat.id, "Hello! What is your first name?", - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -35,7 +36,7 @@ def any_state(message: types.Message, state: StateContext): bot.send_message( message.chat.id, "Your information has been cleared. Type /start to begin again.", - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -44,7 +45,8 @@ def any_state(message: types.Message, state: StateContext): def name_get(message: types.Message, state: StateContext): state.set(MyStates.age) bot.send_message( - message.chat.id, "How old are you?", reply_to_message_id=message.message_id + message.chat.id, "How old are you?", + reply_parameters=ReplyParameters(message_id=message.message_id), ) state.add_data(name=message.text) @@ -65,7 +67,7 @@ def ask_color(message: types.Message, state: StateContext): message.chat.id, "What is your favorite color? Choose from the options below.", reply_markup=keyboard, - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -85,7 +87,7 @@ def ask_hobby(message: types.Message, state: StateContext): message.chat.id, "What is one of your hobbies? Choose from the options below.", reply_markup=keyboard, - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) @@ -124,7 +126,8 @@ def finish(message: types.Message, state: StateContext): ) bot.send_message( - message.chat.id, msg, parse_mode="html", reply_to_message_id=message.message_id + message.chat.id, msg, parse_mode="html", + reply_parameters=ReplyParameters(message_id=message.message_id), ) state.delete() @@ -135,7 +138,7 @@ def age_incorrect(message: types.Message): bot.send_message( message.chat.id, "Please enter a valid number for age.", - reply_to_message_id=message.message_id, + reply_parameters=ReplyParameters(message_id=message.message_id), ) From 57938f7762fae96edcabe3399beffa5c8c233b80 Mon Sep 17 00:00:00 2001 From: thebocher <63579888+thebocher@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:24:58 +0200 Subject: [PATCH 360/480] Update pickle_storage.py fixed typo in StatePickleStorage.save, which didn't allow to save user state, but instead copied the whole content of state file inside "data" --- telebot/storage/pickle_storage.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/storage/pickle_storage.py b/telebot/storage/pickle_storage.py index e11a05043..b4c44e8fa 100644 --- a/telebot/storage/pickle_storage.py +++ b/telebot/storage/pickle_storage.py @@ -254,9 +254,9 @@ def save( message_thread_id, bot_id, ) - data = self._read_from_file() - data[_key]["data"] = data - self._write_to_file(data) + file_data = self._read_from_file() + file_data[_key]["data"] = data + self._write_to_file(file_data) return True def __str__(self) -> str: From 344e52fac5d7cb870cfd683dc9ff67b7443633e9 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 10 Oct 2024 17:51:38 +0400 Subject: [PATCH 361/480] Fix pickle issue with saving data on async --- telebot/asyncio_storage/pickle_storage.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/asyncio_storage/pickle_storage.py b/telebot/asyncio_storage/pickle_storage.py index 723672034..1a63e6961 100644 --- a/telebot/asyncio_storage/pickle_storage.py +++ b/telebot/asyncio_storage/pickle_storage.py @@ -265,9 +265,9 @@ async def save( message_thread_id, bot_id, ) - data = await self._read_from_file() - data[_key]["data"] = data - await self._write_to_file(data) + file_data = await self._read_from_file() + file_data[_key]["data"] = data + await self._write_to_file(file_data) return True def __str__(self) -> str: From 58356c8d7dac1d7a102ed4216e0b2bb20ed1e0d3 Mon Sep 17 00:00:00 2001 From: Maksim Kulis <37274042+maksimkulis@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:57:12 +0300 Subject: [PATCH 362/480] Fix KeyboardButtonRequestChat request_title typing --- telebot/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 043473aee..7efc260cf 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2655,7 +2655,7 @@ def __init__(self, request_id: int, chat_is_channel: bool, chat_is_forum: Option chat_has_username: Optional[bool]=None, chat_is_created: Optional[bool]=None, user_administrator_rights: Optional[ChatAdministratorRights]=None, bot_administrator_rights: Optional[ChatAdministratorRights]=None, bot_is_member: Optional[bool]=None, - request_title: Optional[str]=None, request_photo: Optional[bool]=None, request_username: Optional[bool]=None): + request_title: Optional[bool]=None, request_photo: Optional[bool]=None, request_username: Optional[bool]=None): self.request_id: int = request_id self.chat_is_channel: bool = chat_is_channel self.chat_is_forum: Optional[bool] = chat_is_forum @@ -2664,7 +2664,7 @@ def __init__(self, request_id: int, chat_is_channel: bool, chat_is_forum: Option self.user_administrator_rights: Optional[ChatAdministratorRights] = user_administrator_rights self.bot_administrator_rights: Optional[ChatAdministratorRights] = bot_administrator_rights self.bot_is_member: Optional[bool] = bot_is_member - self.request_title: Optional[str] = request_title + self.request_title: Optional[bool] = request_title self.request_photo: Optional[bool] = request_photo self.request_username: Optional[bool] = request_username From 309f6a267f0a2d0fa451877f19ad15a25b5b4fc4 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 20 Oct 2024 18:24:21 +0300 Subject: [PATCH 363/480] Enable call stack logging for deprecation warnings (optional) --- telebot/types.py | 139 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 127 insertions(+), 12 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 7efc260cf..4bba24cf7 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -4,6 +4,7 @@ from io import IOBase import logging import os +import traceback from pathlib import Path from typing import Dict, List, Optional, Union, Any, Tuple from abc import ABC @@ -19,6 +20,7 @@ DISABLE_KEYLEN_ERROR = False +DEPRECATION_STACK_SHOW_DEPTH = 0 logger = logging.getLogger('TeleBot') @@ -1550,31 +1552,43 @@ def html_caption(self) -> Optional[str]: @property def voice_chat_scheduled(self): logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.video_chat_scheduled @property def voice_chat_started(self): logger.warning('The parameter "voice_chat_started" is deprecated, use "video_chat_started" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.video_chat_started @property def voice_chat_ended(self): logger.warning('The parameter "voice_chat_ended" is deprecated, use "video_chat_ended" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.video_chat_ended @property def voice_chat_participants_invited(self): logger.warning('The parameter "voice_chat_participants_invited" is deprecated, use "video_chat_participants_invited" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.video_chat_participants_invited @property def new_chat_member(self): logger.warning('The parameter "new_chat_member" is deprecated, use "new_chat_members" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return None @property def forward_from(self): logger.warning('The parameter "forward_from" is deprecated, use "forward_origin" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.forward_origin and isinstance(self.forward_origin, MessageOriginUser): return self.forward_origin.sender_user return None @@ -1582,6 +1596,8 @@ def forward_from(self): @property def forward_from_chat(self): logger.warning('The parameter "forward_from_chat" is deprecated, use "forward_origin" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.forward_origin and isinstance(self.forward_origin, MessageOriginChat): return self.forward_origin.sender_chat elif self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): @@ -1591,6 +1607,8 @@ def forward_from_chat(self): @property def forward_from_message_id(self): logger.warning('The parameter "forward_from_message_id" is deprecated, use "forward_origin" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): return self.forward_origin.message_id return None @@ -1598,6 +1616,8 @@ def forward_from_message_id(self): @property def forward_signature(self): logger.warning('The parameter "forward_signature" is deprecated, use "forward_origin" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.forward_origin and isinstance(self.forward_origin, MessageOriginChat): return self.forward_origin.author_signature elif self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): @@ -1607,6 +1627,8 @@ def forward_signature(self): @property def forward_sender_name(self): logger.warning('The parameter "forward_sender_name" is deprecated, use "forward_origin" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.forward_origin and isinstance(self.forward_origin, MessageOriginHiddenUser): return self.forward_origin.sender_user_name return None @@ -1614,6 +1636,8 @@ def forward_sender_name(self): @property def forward_date(self): logger.warning('The parameter "forward_date" is deprecated, use "forward_origin" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.forward_origin: return self.forward_origin.date return None @@ -1621,6 +1645,8 @@ def forward_date(self): @property def user_shared(self): logger.warning('The parameter "user_shared" is deprecated, use "users_shared" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.users_shared @property @@ -1847,6 +1873,8 @@ def __init__(self, file_id, file_unique_id, duration, performer=None, title=None @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @@ -1942,6 +1970,8 @@ def __init__(self, file_id, file_unique_id, thumbnail=None, file_name=None, mime @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @@ -2006,6 +2036,8 @@ def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=N @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @@ -2056,6 +2088,8 @@ def __init__(self, file_id, file_unique_id, length, duration, thumbnail=None, fi @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @@ -2598,7 +2632,9 @@ class KeyboardButtonRequestUser(KeyboardButtonRequestUsers): def __init__( self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, max_quantity: Optional[int]=None) -> None: - logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') + logger.warning('The class "KeyboardButtonRequestUser" is deprecated, use "KeyboardButtonRequestUsers" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) super().__init__(request_id, user_is_bot=user_is_bot, user_is_premium=user_is_premium, max_quantity=max_quantity) @@ -2746,6 +2782,8 @@ def __init__(self, text: str, request_contact: Optional[bool]=None, self.request_users: Optional[KeyboardButtonRequestUsers] = request_users if request_user is not None: logger.warning('The parameter "request_user" is deprecated, use "request_users" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if self.request_users is None: # noinspection PyTypeChecker self.request_users = request_user @@ -3233,6 +3271,8 @@ def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_ed @property def can_manage_voice_chats(self): logger.warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.can_manage_video_chats @@ -3558,6 +3598,8 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send # Telegram passes can_send_media_messages in Chat.permissions. Temporary created parameter "de_json" allows avoid # deprection warning and individual parameters overriding. logger.warning('The parameter "can_send_media_messages" is deprecated. Use individual parameters like "can_send_audios", "can_send_documents" etc.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) self.can_send_audios: Optional[bool] = can_send_media_messages self.can_send_documents: Optional[bool] = can_send_media_messages self.can_send_photos: Optional[bool] = can_send_media_messages @@ -3928,7 +3970,9 @@ def __init__(self, message_text: str, parse_mode: Optional[str] = None, entities self.link_preview_options: Optional[LinkPreviewOptions] = link_preview_options if disable_web_page_preview is not None: logger.warning('The parameter "disable_web_page_preview" is deprecated. Use "link_preview_options" instead.') - + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + if link_preview_options: logger.warning('Both "link_preview_options" and "disable_web_page_preview" parameters are set: conflicting, "disable_web_page_preview" is deprecated') else: @@ -4434,16 +4478,22 @@ def __init__(self, id: str, title: str, input_message_content: InputMessageConte @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_width @property def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_height def to_dict(self): @@ -4535,6 +4585,8 @@ def __init__(self, id: str, photo_url: str, thumbnail_url: str, photo_width: Opt @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url def to_dict(self): @@ -4629,11 +4681,15 @@ def __init__(self, id: str, gif_url: str, thumbnail_url: str, gif_width: Optiona @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_mime_type(self) -> str: logger.warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_mime_type def to_dict(self): @@ -4729,11 +4785,15 @@ def __init__(self, id: str, mpeg4_url: str, thumbnail_url: str, mpeg4_width: Opt @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_mime_type(self) -> str: logger.warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_mime_type def to_dict(self): @@ -4835,6 +4895,8 @@ def __init__(self, id: str, video_url: str, mime_type: str, thumbnail_url: str, @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url def to_dict(self): @@ -5052,16 +5114,22 @@ def __init__(self, id: str, title: str, document_url: str, mime_type: str, capti @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_width @property def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_height def to_dict(self): @@ -5151,16 +5219,22 @@ def __init__(self, id: str, title: str, latitude: float, longitude: float, horiz @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_width @property def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_height def to_dict(self): @@ -5261,16 +5335,22 @@ def __init__(self, id: str, title: str, latitude: float, longitude: float, addre @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_width @property def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_height def to_dict(self): @@ -5356,16 +5436,22 @@ def __init__(self, id: str, phone_number: str, first_name: str, last_name: Optio @property def thumb_url(self) -> str: logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_url @property def thumb_width(self) -> int: logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_width @property def thumb_height(self) -> int: logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail_height def to_dict(self): @@ -6054,6 +6140,8 @@ def __init__(self, file_id, file_unique_id, width=None, height=None, duration=No @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @@ -6470,30 +6558,29 @@ def __init__(self, name, title, sticker_type, stickers, thumbnail=None, **kwargs @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @property def contains_masks(self) -> bool: - """ - Deprecated since Bot API 6.2, use sticker_type instead. - """ logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type instead"') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.sticker_type == 'mask' @property def is_animated(self) -> bool: - """ - Deprecated since Bot API 7.2. Stickers can be mixed now. - """ logger.warning('The parameter "is_animated" is deprecated since Bot API 7.2. Stickers can now be mixed') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return False @property def is_video(self) -> bool: - """ - Deprecated since Bot API 7.2. Stickers can be mixed now. - """ logger.warning('The parameter "is_video" is deprecated since Bot API 7.2. Stickers can now be mixed') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return False @@ -6593,6 +6680,8 @@ def __init__(self, file_id, file_unique_id, type, width, height, is_animated, @property def thumb(self) -> Optional[PhotoSize]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail @@ -6811,6 +6900,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail def to_dict(self): @@ -6898,6 +6989,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail def to_dict(self): @@ -6972,6 +7065,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail def to_dict(self): @@ -7035,6 +7130,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.thumbnail def to_dict(self): @@ -7204,6 +7301,8 @@ def __init__( self.type: str = type if poll_type is not None: logger.warning("Poll: poll_type parameter is deprecated. Use type instead.") + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) if type is None: self.type: str = poll_type self.allows_multiple_answers: bool = allows_multiple_answers @@ -7447,6 +7546,8 @@ class VoiceChatStarted(VideoChatStarted): def __init__(self): logger.warning('VoiceChatStarted is deprecated. Use VideoChatStarted instead.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) super().__init__() @@ -7479,6 +7580,8 @@ class VoiceChatScheduled(VideoChatScheduled): """ def __init__(self, *args, **kwargs): logger.warning('VoiceChatScheduled is deprecated. Use VideoChatScheduled instead.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) super().__init__(*args, **kwargs) @@ -7510,6 +7613,8 @@ class VoiceChatEnded(VideoChatEnded): """ def __init__(self, *args, **kwargs): logger.warning('VoiceChatEnded is deprecated. Use VideoChatEnded instead.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) super().__init__(*args, **kwargs) @@ -7543,6 +7648,8 @@ class VoiceChatParticipantsInvited(VideoChatParticipantsInvited): """ def __init__(self, *args, **kwargs): logger.warning('VoiceChatParticipantsInvited is deprecated. Use VideoChatParticipantsInvited instead.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) super().__init__(*args, **kwargs) @@ -8190,6 +8297,8 @@ def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], forma if not self.format: logger.warning("Deprecation warning. 'format' parameter is required in InputSticker. Setting format to 'static'.") + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) self.format = "static" if service_utils.is_string(self.sticker): @@ -9308,11 +9417,15 @@ def __init__(self, request_id: int, users: List[SharedUser], **kwargs): @property def user_id(self) -> None: logger.warning('The parameter "user_id" is deprecated, use "user_ids" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return None @property def user_ids(self) -> List[SharedUser]: logger.warning('The parameter "user_ids" is deprecated, use "users" instead') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return self.users @@ -9613,7 +9726,9 @@ def __init__(self, chat, message_id, date, **kwargs): @staticmethod def __universal_deprecation(property_name): - logger.warning(f'Deprecation warning: the filed "{property_name}" is not accessible for InaccessibleMessage. You should check if your object is Message instance before access.') + logger.warning(f'Deprecation warning: the field "{property_name}" is not accessible for InaccessibleMessage. You should check if your object is Message instance before access.') + if DEPRECATION_STACK_SHOW_DEPTH: + logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) return None def __getattr__(self, item): From b6db6a9ad66aca8402e176ca9a94019858e9ec0d Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 1 Nov 2024 15:34:54 +0400 Subject: [PATCH 364/480] Added the class CopyTextButton and the field copy_text in the class InlineKeyboardButton allowing bots to send and receive inline buttons that copy arbitrary text. --- telebot/types.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 7efc260cf..e882e9d71 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -2932,6 +2932,9 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable) the first row and can only be used in invoice messages. :type pay: :obj:`bool` + :param copy_text: Optional. Description of the button that copies the specified text to the clipboard. + :type copy_text: :class:`telebot.types.CopyTextButton` + :return: Instance of the class :rtype: :class:`telebot.types.InlineKeyboardButton` """ @@ -2945,13 +2948,15 @@ def de_json(cls, json_string): obj['web_app'] = WebAppInfo.de_json(obj.get('web_app')) if 'switch_inline_query_chosen_chat' in obj: obj['switch_inline_query_chosen_chat'] = SwitchInlineQueryChosenChat.de_json(obj.get('switch_inline_query_chosen_chat')) + if 'copy_text' in obj: + obj['copy_text'] = CopyTextButton.de_json(obj.get('copy_text')) return cls(**obj) def __init__(self, text: str, url: Optional[str]=None, callback_data: Optional[str]=None, web_app: Optional[WebAppInfo]=None, switch_inline_query: Optional[str]=None, switch_inline_query_current_chat: Optional[str]=None, switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat]=None, callback_game=None, pay: Optional[bool]=None, - login_url: Optional[LoginUrl]=None, **kwargs): + login_url: Optional[LoginUrl]=None, copy_text: Optional[CopyTextButton]=None, **kwargs): self.text: str = text self.url: Optional[str] = url self.callback_data: Optional[str] = callback_data @@ -2962,6 +2967,7 @@ def __init__(self, text: str, url: Optional[str]=None, callback_data: Optional[s self.callback_game = callback_game # Not Implemented self.pay: Optional[bool] = pay self.login_url: Optional[LoginUrl] = login_url + self.copy_text: Optional[CopyTextButton] = copy_text def to_json(self): return json.dumps(self.to_dict()) @@ -2986,6 +2992,8 @@ def to_dict(self): json_dict['login_url'] = self.login_url.to_dict() if self.switch_inline_query_chosen_chat is not None: json_dict['switch_inline_query_chosen_chat'] = self.switch_inline_query_chosen_chat.to_dict() + if self.copy_text is not None: + json_dict['copy_text'] = self.copy_text.to_dict() return json_dict @@ -10910,3 +10918,33 @@ def de_json(cls, json_string): obj['from_user'] = User.de_json(obj['from_user']) return cls(**obj) + +class CopyTextButton(JsonSerializable, JsonDeserializable): + """ + This object represents an inline keyboard button that copies specified text to the clipboard. + + Telegram documentation: https://core.telegram.org/bots/api#copytextbutton + + :param text: The text to be copied to the clipboard; 1-256 characters + :type text: :obj:`str` + + :return: Instance of the class + :rtype: :class:`CopyTextButton` + """ + def __init__(self, text: str, **kwargs): + self.text: str = text + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'text': self.text + } + return data + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) From f9cc905ef46d0e905c46378112ffc2cffe669901 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 1 Nov 2024 16:18:53 +0400 Subject: [PATCH 365/480] Added the parameter allow_paid_broadcast to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendPaidMedia, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendPoll, sendDice, sendInvoice, sendGame, sendMediaGroup and copyMessage. --- telebot/__init__.py | 170 ++++++++++++++++++++++++++++-------- telebot/apihelper.py | 78 +++++++++++++---- telebot/async_telebot.py | 176 ++++++++++++++++++++++++++++++-------- telebot/asyncio_helper.py | 82 ++++++++++++++---- 4 files changed, 394 insertions(+), 112 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index a79c2ea50..59de38db5 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1670,7 +1670,8 @@ def send_message( reply_parameters: Optional[types.ReplyParameters]=None, link_preview_options : Optional[types.LinkPreviewOptions]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send text messages. @@ -1729,6 +1730,10 @@ def send_message( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1777,7 +1782,7 @@ def send_message( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, entities=entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, link_preview_options=link_preview_options, business_connection_id=business_connection_id, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) def forward_message( @@ -1839,7 +1844,8 @@ def copy_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - show_caption_above_media: Optional[bool]=None) -> types.MessageID: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. @@ -1894,6 +1900,10 @@ def copy_message( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -1926,7 +1936,7 @@ def copy_message( parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - show_caption_above_media=show_caption_above_media)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) def delete_message(self, chat_id: Union[int, str], message_id: int, @@ -2076,7 +2086,8 @@ def send_dice( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -2121,6 +2132,10 @@ def send_dice( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2150,7 +2165,7 @@ def send_dice( self.token, chat_id, emoji=emoji, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) @@ -2169,7 +2184,8 @@ def send_photo( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - show_caption_above_media: Optional[bool]=None) -> types.Message: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2229,6 +2245,10 @@ def send_photo( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2262,7 +2282,7 @@ def send_photo( caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) def send_audio( @@ -2282,7 +2302,8 @@ def send_audio( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -2358,6 +2379,10 @@ def send_audio( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2393,7 +2418,7 @@ def send_audio( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) def send_voice( @@ -2410,7 +2435,8 @@ def send_voice( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -2467,6 +2493,10 @@ def send_voice( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -2497,7 +2527,7 @@ def send_voice( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -2519,7 +2549,8 @@ def send_document( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send general files. @@ -2588,6 +2619,10 @@ def send_document( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2632,7 +2667,7 @@ def send_document( timeout=timeout, caption=caption, thumbnail=thumbnail, caption_entities=caption_entities, disable_content_type_detection=disable_content_type_detection, visible_file_name=visible_file_name, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -2650,7 +2685,8 @@ def send_sticker( emoji: Optional[str]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -2702,6 +2738,10 @@ def send_sticker( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2736,7 +2776,7 @@ def send_sticker( reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -2763,7 +2803,8 @@ def send_video( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - show_caption_above_media: Optional[bool]=None) -> types.Message: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2843,6 +2884,10 @@ def send_video( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2884,7 +2929,7 @@ def send_video( thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast) ) @@ -2909,7 +2954,8 @@ def send_animation( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - show_caption_above_media: Optional[bool]=None) -> types.Message: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -2988,6 +3034,10 @@ def send_animation( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3024,7 +3074,7 @@ def send_animation( thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast) ) @@ -3043,7 +3093,8 @@ def send_video_note( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -3104,6 +3155,10 @@ def send_video_note( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3137,7 +3192,7 @@ def send_video_note( self.token, chat_id, data, duration=duration, length=length, reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) def send_paid_media( @@ -3146,7 +3201,7 @@ def send_paid_media( show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, - payload: Optional[str]=None + payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None ) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -3192,6 +3247,10 @@ def send_paid_media( :param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes. :type payload: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3201,7 +3260,7 @@ def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - payload=payload) + payload=payload, allow_paid_broadcast=allow_paid_broadcast) ) @@ -3218,7 +3277,8 @@ def send_media_group( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> List[types.Message]: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -3258,6 +3318,10 @@ def send_media_group( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -3291,7 +3355,7 @@ def send_media_group( result = apihelper.send_media_group( self.token, chat_id, media, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) return [types.Message.de_json(msg) for msg in result] @@ -3311,7 +3375,8 @@ def send_location( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -3370,6 +3435,10 @@ def send_location( :parameter message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3400,7 +3469,7 @@ def send_location( disable_notification=disable_notification, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, proximity_alert_radius=proximity_alert_radius, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -3531,7 +3600,8 @@ def send_venue( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -3597,6 +3667,10 @@ def send_venue( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3627,7 +3701,7 @@ def send_venue( foursquare_type=foursquare_type, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, google_place_id=google_place_id, google_place_type=google_place_type, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -3643,7 +3717,8 @@ def send_contact( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -3696,6 +3771,10 @@ def send_contact( :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3725,7 +3804,7 @@ def send_contact( self.token, chat_id, phone_number, first_name, last_name=last_name, vcard=vcard, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -4982,7 +5061,8 @@ def send_game( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Used to send the game. @@ -5024,6 +5104,10 @@ def send_game( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5056,7 +5140,7 @@ def send_game( self.token, chat_id, game_short_name, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) @@ -5161,7 +5245,8 @@ def send_invoice( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Sends invoice. @@ -5270,6 +5355,10 @@ def send_invoice( :param message_effect_id: The identifier of a message effect, which will be applied to the sent message :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5309,7 +5398,7 @@ def send_invoice( provider_data=provider_data, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) def create_invoice_link(self, @@ -5441,7 +5530,8 @@ def send_poll( business_connection_id: Optional[str]=None, question_parse_mode: Optional[str] = None, question_entities: Optional[List[types.MessageEntity]] = None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -5523,6 +5613,10 @@ def send_poll( :param message_effect_id: Unique identifier of the message effect to apply to the sent message :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5578,7 +5672,7 @@ def send_poll( protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, question_parse_mode=question_parse_mode, question_entities=question_entities, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index c46b108c8..92d419c45 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -245,7 +245,7 @@ def send_message( parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, link_preview_options=None, - business_connection_id=None, message_effect_id=None): + business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -270,6 +270,8 @@ def send_message( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, method='post') @@ -428,7 +430,7 @@ def forward_message( def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, - reply_parameters=None, show_caption_above_media=None): + reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -451,6 +453,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['message_thread_id'] = message_thread_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -458,7 +462,7 @@ def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, - business_connection_id=None, message_effect_id=None): + business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -479,6 +483,8 @@ def send_dice( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -488,7 +494,7 @@ def send_photo( parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -524,13 +530,15 @@ def send_photo( payload['message_effect_id'] = message_effect_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, payload=None): + business_connection_id=None, payload=None, allow_paid_broadcast=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -554,6 +562,8 @@ def send_paid_media( _payload['business_connection_id'] = business_connection_id if payload: _payload['payload'] = payload + if allow_paid_broadcast is not None: + _payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request( token, method_url, params=_payload, method='post' if files else 'get', @@ -564,7 +574,7 @@ def send_media_group( token, chat_id, media, disable_notification=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendMediaGroup' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -582,6 +592,8 @@ def send_media_group( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request( token, method_url, params=payload, method='post' if files else 'get', @@ -595,7 +607,7 @@ def send_location( timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -622,6 +634,8 @@ def send_location( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -678,7 +692,7 @@ def send_venue( foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -705,6 +719,8 @@ def send_venue( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -712,7 +728,7 @@ def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -735,6 +751,8 @@ def send_contact( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -755,7 +773,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -805,6 +823,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['message_effect_id'] = message_effect_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') @@ -813,7 +833,8 @@ def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, - has_spoiler=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None): + has_spoiler=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, + allow_paid_broadcast=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -861,13 +882,15 @@ def send_animation( payload['message_effect_id'] = message_effect_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -899,12 +922,15 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None, reply_parameters=None,business_connection_id=None, message_effect_id=None): + message_thread_id=None, reply_parameters=None,business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -942,13 +968,15 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -992,6 +1020,8 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') @@ -999,7 +1029,7 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -1044,6 +1074,8 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1545,7 +1577,8 @@ def delete_message(token, chat_id, message_id, timeout=None): def send_game( token, chat_id, game_short_name, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, message_effect_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: @@ -1564,6 +1597,8 @@ def send_game( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -1629,7 +1664,8 @@ def send_invoice( send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, + allow_paid_broadcast=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1662,6 +1698,7 @@ def send_invoice( :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only :param reply_parameters: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :param allow_paid_broadcast: :return: """ method_url = r'sendInvoice' @@ -1714,6 +1751,8 @@ def send_invoice( payload['message_effect_id'] = message_effect_id if provider_token is not None: payload['provider_token'] = provider_token + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) @@ -1974,7 +2013,8 @@ def send_poll( is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None, explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, - reply_parameters=None, business_connection_id=None, question_parse_mode=None, question_entities=None, message_effect_id=None): + reply_parameters=None, business_connection_id=None, question_parse_mode=None, question_entities=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -2025,6 +2065,8 @@ def send_poll( payload['question_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(question_entities)) if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return _make_request(token, method_url, params=payload) def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ef35d109a..3874429ad 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3161,7 +3161,8 @@ async def send_message( reply_parameters: Optional[types.ReplyParameters]=None, link_preview_options: Optional[types.LinkPreviewOptions]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send text messages. @@ -3220,6 +3221,10 @@ async def send_message( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3275,7 +3280,7 @@ async def send_message( self.token, chat_id, text, reply_markup, parse_mode, disable_notification, timeout, entities, protect_content, message_thread_id, reply_parameters, link_preview_options, business_connection_id, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -3334,7 +3339,8 @@ async def copy_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - show_caption_above_media: Optional[bool]=None) -> types.MessageID: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, @@ -3389,6 +3395,10 @@ async def copy_message( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -3420,7 +3430,8 @@ async def copy_message( return types.MessageID.de_json( await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, disable_notification, reply_markup, - timeout, protect_content, message_thread_id, reply_parameters, show_caption_above_media=show_caption_above_media)) + timeout, protect_content, message_thread_id, reply_parameters, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast)) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -3557,7 +3568,8 @@ async def send_dice( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -3602,6 +3614,10 @@ async def send_dice( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3632,7 +3648,8 @@ async def send_dice( return types.Message.de_json( await asyncio_helper.send_dice( self.token, chat_id, emoji, disable_notification, - reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast)) async def send_photo( @@ -3650,7 +3667,8 @@ async def send_photo( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - show_caption_above_media: Optional[bool]=None) -> types.Message: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -3710,6 +3728,10 @@ async def send_photo( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3744,7 +3766,7 @@ async def send_photo( self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) async def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -3763,7 +3785,8 @@ async def send_audio( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -3839,6 +3862,10 @@ async def send_audio( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3875,7 +3902,7 @@ async def send_audio( await asyncio_helper.send_audio( self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], @@ -3891,7 +3918,8 @@ async def send_voice( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -3948,6 +3976,10 @@ async def send_voice( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -3979,7 +4011,8 @@ async def send_voice( await asyncio_helper.send_voice( self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, - protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast)) async def send_document( self, chat_id: Union[int, str], document: Union[Any, str], @@ -4000,7 +4033,8 @@ async def send_document( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send general files. @@ -4069,6 +4103,10 @@ async def send_document( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4117,7 +4155,7 @@ async def send_document( disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content, - message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id)) + message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], @@ -4132,7 +4170,8 @@ async def send_sticker( emoji: Optional[str]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -4184,6 +4223,10 @@ async def send_sticker( :param message_effect_id: Unique identifier for the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4222,7 +4265,7 @@ async def send_sticker( reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id)) + message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -4247,7 +4290,8 @@ async def send_video( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - show_caption_above_media: Optional[bool]=None) -> types.Message: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4327,6 +4371,10 @@ async def send_video( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4369,7 +4417,7 @@ async def send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -4392,7 +4440,8 @@ async def send_animation( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - show_caption_above_media: Optional[bool]=None) -> types.Message: + show_caption_above_media: Optional[bool]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -4471,6 +4520,10 @@ async def send_animation( :param show_caption_above_media: Pass True, if the caption must be shown above the message media. Supported only for animation, photo and video messages. :type show_caption_above_media: :obj:`bool` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4508,7 +4561,7 @@ async def send_animation( self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, - message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media)) + message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -4525,7 +4578,8 @@ async def send_video_note( thumb: Optional[Union[Any, str]]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -4586,6 +4640,10 @@ async def send_video_note( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4620,7 +4678,8 @@ async def send_video_note( return types.Message.de_json( await asyncio_helper.send_video_note( self.token, chat_id, data, duration, length, reply_markup, - disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast)) async def send_paid_media( self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], @@ -4628,7 +4687,7 @@ async def send_paid_media( show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, - payload: Optional[str]=None) -> types.Message: + payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -4673,6 +4732,10 @@ async def send_paid_media( :param payload: Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes. :type payload: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4682,7 +4745,7 @@ async def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - payload=payload)) + payload=payload, allow_paid_broadcast=allow_paid_broadcast)) async def send_media_group( self, chat_id: Union[int, str], @@ -4697,7 +4760,8 @@ async def send_media_group( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> List[types.Message]: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -4737,6 +4801,10 @@ async def send_media_group( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -4770,7 +4838,8 @@ async def send_media_group( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply result = await asyncio_helper.send_media_group( - self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id) + self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast) return [types.Message.de_json(msg) for msg in result] async def send_location( @@ -4789,7 +4858,8 @@ async def send_location( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -4848,6 +4918,10 @@ async def send_location( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4880,7 +4954,7 @@ async def send_location( self.token, chat_id, latitude, longitude, live_period, reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, - protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def edit_message_live_location( self, latitude: float, longitude: float, @@ -5005,7 +5079,8 @@ async def send_venue( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -5071,6 +5146,10 @@ async def send_venue( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -5103,7 +5182,8 @@ async def send_venue( await asyncio_helper.send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, disable_notification, reply_markup, timeout, - google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, + allow_paid_broadcast=allow_paid_broadcast)) async def send_contact( @@ -5119,7 +5199,8 @@ async def send_contact( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -5173,6 +5254,10 @@ async def send_contact( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -5204,7 +5289,7 @@ async def send_contact( await asyncio_helper.send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_chat_action( @@ -6406,7 +6491,8 @@ async def send_game( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Used to send the game. @@ -6448,6 +6534,10 @@ async def send_game( :param message_effect_id: Identifier of the message effect. :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6478,7 +6568,7 @@ async def send_game( result = await asyncio_helper.send_game( self.token, chat_id, game_short_name, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) return types.Message.de_json(result) async def set_game_score( @@ -6577,7 +6667,8 @@ async def send_invoice( protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Sends invoice. @@ -6686,6 +6777,10 @@ async def send_invoice( :param message_effect_id: The identifier of a message effect to be applied to the message :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6720,7 +6815,7 @@ async def send_invoice( send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification, reply_markup, provider_data, timeout, max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters, - message_effect_id=message_effect_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) return types.Message.de_json(result) @@ -6851,7 +6946,8 @@ async def send_poll( business_connection_id: Optional[str]=None, question_parse_mode: Optional[str] = None, question_entities: Optional[List[types.MessageEntity]] = None, - message_effect_id: Optional[str]=None) -> types.Message: + message_effect_id: Optional[str]=None, + allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send a native poll. On success, the sent Message is returned. @@ -6937,6 +7033,10 @@ async def send_poll( :param message_effect_id: Identifier of the message effect to apply to the sent message :type message_effect_id: :obj:`str` + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee + of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance + :type allow_paid_broadcast: :obj:`bool` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6989,7 +7089,7 @@ async def send_poll( disable_notification, reply_markup, timeout, explanation_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, question_parse_mode=question_parse_mode, question_entities=question_entities, - message_effect_id=message_effect_id)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def stop_poll( self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 0bd447f18..b21b7f9f0 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -283,7 +283,8 @@ async def send_message( reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, - message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None, message_effect_id=None): + message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -308,6 +309,8 @@ async def send_message( params['business_connection_id'] = business_connection_id if message_effect_id: params['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + params['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_name, params=params, method='post') @@ -418,7 +421,8 @@ async def forward_message( async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, - reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None): + reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, + allow_paid_broadcast=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -441,6 +445,8 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['message_thread_id'] = message_thread_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) @@ -448,7 +454,7 @@ async def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, - message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -469,6 +475,8 @@ async def send_dice( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) @@ -478,7 +486,7 @@ async def send_photo( parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, - business_connection_id=None, message_effect_id=None, show_caption_above_media=None): + business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -514,13 +522,15 @@ async def send_photo( payload['message_effect_id'] = message_effect_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, payload=None): + business_connection_id=None, payload=None, allow_paid_broadcast=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -545,6 +555,8 @@ async def send_paid_media( _payload['business_connection_id'] = business_connection_id if payload: _payload['payload'] = payload + if allow_paid_broadcast is not None: + _payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request( token, method_url, params=_payload, @@ -554,7 +566,8 @@ async def send_paid_media( async def send_media_group( token, chat_id, media, disable_notification=None, - timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendMediaGroup' media_json, files = await convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -572,6 +585,8 @@ async def send_media_group( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request( token, method_url, params=payload, method='post' if files else 'get', @@ -584,7 +599,7 @@ async def send_location( reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -611,6 +626,8 @@ async def send_location( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) @@ -668,7 +685,7 @@ async def send_venue( reply_markup=None, timeout=None, google_place_id=None, google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -695,13 +712,16 @@ async def send_venue( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) async def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -724,6 +744,8 @@ async def send_contact( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) @@ -743,7 +765,7 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -793,6 +815,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['message_effect_id'] = message_effect_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -800,7 +824,8 @@ async def send_animation( token, chat_id, data, duration=None, caption=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, width=None, height=None, protect_content=None, message_thread_id=None, - has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None): + has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, + allow_paid_broadcast=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -848,12 +873,15 @@ async def send_animation( payload['message_effect_id'] = message_effect_id if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, - protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None, message_effect_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -885,12 +913,14 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_ payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -928,13 +958,15 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, rep payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None): + message_effect_id=None, allow_paid_broadcast=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -978,13 +1010,16 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None, - message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -1029,6 +1064,8 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1528,7 +1565,8 @@ async def delete_message(token, chat_id, message_id, timeout=None): async def send_game( token, chat_id, game_short_name, disable_notification=None, reply_markup=None, timeout=None, - protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None): + protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendGame' payload = {'chat_id': chat_id, 'game_short_name': game_short_name} if disable_notification is not None: @@ -1547,6 +1585,8 @@ async def send_game( payload['business_connection_id'] = business_connection_id if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) @@ -1612,7 +1652,7 @@ async def send_invoice( send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None): + protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, allow_paid_broadcast=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1646,6 +1686,7 @@ async def send_invoice( :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only :param reply_parameters: A JSON-serialized object for an inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :param allow_paid_broadcast: :return: """ method_url = r'sendInvoice' @@ -1698,6 +1739,8 @@ async def send_invoice( payload['message_effect_id'] = message_effect_id if provider_token is not None: payload['provider_token'] = provider_token + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) @@ -1954,7 +1997,8 @@ async def send_poll( explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None, disable_notification=False, reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None, - reply_parameters=None,business_connection_id=None, question_parse_mode=None, question_entities=None, message_effect_id=None): + reply_parameters=None,business_connection_id=None, question_parse_mode=None, question_entities=None, message_effect_id=None, + allow_paid_broadcast=None): method_url = r'sendPoll' payload = { 'chat_id': str(chat_id), @@ -2006,6 +2050,8 @@ async def send_poll( payload['question_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(question_entities)) if message_effect_id: payload['message_effect_id'] = message_effect_id + if allow_paid_broadcast is not None: + payload['allow_paid_broadcast'] = allow_paid_broadcast return await _process_request(token, method_url, params=payload) From be047fccc6a8d3d72f19def4e55fcb8579cb8e39 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 1 Nov 2024 16:23:22 +0400 Subject: [PATCH 366/480] Added the class TransactionPartnerTelegramApi for transactions related to paid broadcasted messages. --- telebot/types.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index e882e9d71..e93f05685 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10394,6 +10394,8 @@ def de_json(cls, json_string): return TransactionPartnerUser.de_json(obj) elif obj["type"] == "telegram_ads": return TransactionPartnerTelegramAds.de_json(obj) + elif obj["type"] == "telegram_api": + return TransactionPartnerTelegramApi.de_json(obj) elif obj["type"] == "other": return TransactionPartnerOther.de_json(obj) @@ -10429,6 +10431,33 @@ def de_json(cls, json_string): return cls(**obj) +class TransactionPartnerTelegramApi(TransactionPartner): + """ + Describes a transaction with payment for paid broadcasting. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartnertelegramapi + + :param type: Type of the transaction partner, always “telegram_api” + :type type: :obj:`str` + + :param request_count: The number of successful requests that exceeded regular limits and were therefore billed + :type request_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerTelegramApi` + """ + + def __init__(self, type, request_count, **kwargs): + self.type: str = type + self.request_count: int = request_count + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + + # noinspection PyShadowingBuiltins class TransactionPartnerUser(TransactionPartner): """ From c16e264e4a281092aac6a5fa72cd33cb1b418619 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 1 Nov 2024 16:24:01 +0400 Subject: [PATCH 367/480] Introduced the ability to add media to existing text messages using the method editMessageMedia --- telebot/__init__.py | 9 +++++---- telebot/async_telebot.py | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 59de38db5..62cae3f96 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4969,10 +4969,11 @@ def edit_message_media( business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: """ - Use this method to edit animation, audio, document, photo, or video messages. - If a message is a part of a message album, then it can be edited only to a photo or a video. - Otherwise, message type can be changed arbitrarily. When inline message is edited, new file can't be uploaded. - Use previously uploaded file via its file_id or specify a URL. + Use this method to edit animation, audio, document, photo, or video messages, or to add media to text messages. + If a message is part of a message album, then it can be edited only to an audio for audio albums, only to a document for document albums and to a photo or a video otherwise. + When an inline message is edited, a new file can't be uploaded; use a previously uploaded file via its file_id or specify a URL. + On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. + Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. Telegram documentation: https://core.telegram.org/bots/api#editmessagemedia diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 3874429ad..75ce41346 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6405,10 +6405,11 @@ async def edit_message_media( business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: """ - Use this method to edit animation, audio, document, photo, or video messages. - If a message is a part of a message album, then it can be edited only to a photo or a video. - Otherwise, message type can be changed arbitrarily. When inline message is edited, new file can't be uploaded. - Use previously uploaded file via its file_id or specify a URL. + Use this method to edit animation, audio, document, photo, or video messages, or to add media to text messages. + If a message is part of a message album, then it can be edited only to an audio for audio albums, only to a document for document albums and to a photo or a video otherwise. + When an inline message is edited, a new file can't be uploaded; use a previously uploaded file via its file_id or specify a URL. + On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. + Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. Telegram documentation: https://core.telegram.org/bots/api#editmessagemedia From cabd0cb587da8f8e94871aa3723f0de338f53718 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 1 Nov 2024 16:33:20 +0400 Subject: [PATCH 368/480] Added support for hashtag and cashtag entities with a specified chat username that opens a search for the relevant tag within the specified chat. --- telebot/types.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index e93f05685..a4b676c03 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1639,11 +1639,10 @@ class MessageEntity(Dictionaryable, JsonSerializable, JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#messageentity - :param type: Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag), “cashtag” ($USD), - “bot_command” (/start@jobs_bot),“url” (https://telegram.org), “email” (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), - “bold” (bold text), “italic” (italic text), “underline” (underlined text), “strikethrough” (strikethrough text), - “spoiler” (spoiler message), “blockquote” (block quotation), “expandable_blockquote” (collapsed-by-default block quotation), - “code” (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), + :param type: Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag or #hashtag@chatusername), “cashtag” ($USD or $USD@chatusername), + “bot_command” (/start@jobs_bot), “url” (https://telegram.org), “email” (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), “bold” (bold text), + “italic” (italic text), “underline” (underlined text), “strikethrough” (strikethrough text), “spoiler” (spoiler message), “blockquote” (block quotation), + “expandable_blockquote” (collapsed-by-default block quotation), “code” (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), “text_mention” (for users without usernames), “custom_emoji” (for inline custom emoji stickers) :type type: :obj:`str` From 6044655f28828841a5ec4be1ec571d8d60763e44 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 1 Nov 2024 16:33:56 +0400 Subject: [PATCH 369/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1959744fa..43676d2d1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From 822afdf23d5a931a6c0908367bf7d016b33363f3 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 3 Nov 2024 16:51:51 +0300 Subject: [PATCH 370/480] Wrapped deprecation logging to a single function --- telebot/types.py | 256 +++++++++++++---------------------------------- 1 file changed, 72 insertions(+), 184 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 4bba24cf7..03a851620 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -24,6 +24,16 @@ logger = logging.getLogger('TeleBot') + +def log_deprecation_warning(warning_message, logging_level=logging.WARNING): + """ + Logs a deprecation warning message. + """ + logger.log(logging_level, warning_message) + if DEPRECATION_STACK_SHOW_DEPTH: + logger.log(logging_level, "".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + + class JsonSerializable(object): """ Subclasses of this class are guaranteed to be able to be converted to JSON format. @@ -1551,53 +1561,39 @@ def html_caption(self) -> Optional[str]: @property def voice_chat_scheduled(self): - logger.warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "voice_chat_scheduled" is deprecated, use "video_chat_scheduled" instead') return self.video_chat_scheduled @property def voice_chat_started(self): - logger.warning('The parameter "voice_chat_started" is deprecated, use "video_chat_started" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "voice_chat_started" is deprecated, use "video_chat_started" instead') return self.video_chat_started @property def voice_chat_ended(self): - logger.warning('The parameter "voice_chat_ended" is deprecated, use "video_chat_ended" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "voice_chat_ended" is deprecated, use "video_chat_ended" instead') return self.video_chat_ended @property def voice_chat_participants_invited(self): - logger.warning('The parameter "voice_chat_participants_invited" is deprecated, use "video_chat_participants_invited" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "voice_chat_participants_invited" is deprecated, use "video_chat_participants_invited" instead') return self.video_chat_participants_invited @property def new_chat_member(self): - logger.warning('The parameter "new_chat_member" is deprecated, use "new_chat_members" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "new_chat_member" is deprecated, use "new_chat_members" instead') return None @property def forward_from(self): - logger.warning('The parameter "forward_from" is deprecated, use "forward_origin" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "forward_from" is deprecated, use "forward_origin" instead') if self.forward_origin and isinstance(self.forward_origin, MessageOriginUser): return self.forward_origin.sender_user return None @property def forward_from_chat(self): - logger.warning('The parameter "forward_from_chat" is deprecated, use "forward_origin" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "forward_from_chat" is deprecated, use "forward_origin" instead') if self.forward_origin and isinstance(self.forward_origin, MessageOriginChat): return self.forward_origin.sender_chat elif self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): @@ -1606,18 +1602,14 @@ def forward_from_chat(self): @property def forward_from_message_id(self): - logger.warning('The parameter "forward_from_message_id" is deprecated, use "forward_origin" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "forward_from_message_id" is deprecated, use "forward_origin" instead') if self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): return self.forward_origin.message_id return None @property def forward_signature(self): - logger.warning('The parameter "forward_signature" is deprecated, use "forward_origin" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "forward_signature" is deprecated, use "forward_origin" instead') if self.forward_origin and isinstance(self.forward_origin, MessageOriginChat): return self.forward_origin.author_signature elif self.forward_origin and isinstance(self.forward_origin, MessageOriginChannel): @@ -1626,27 +1618,21 @@ def forward_signature(self): @property def forward_sender_name(self): - logger.warning('The parameter "forward_sender_name" is deprecated, use "forward_origin" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "forward_sender_name" is deprecated, use "forward_origin" instead') if self.forward_origin and isinstance(self.forward_origin, MessageOriginHiddenUser): return self.forward_origin.sender_user_name return None @property def forward_date(self): - logger.warning('The parameter "forward_date" is deprecated, use "forward_origin" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "forward_date" is deprecated, use "forward_origin" instead') if self.forward_origin: return self.forward_origin.date return None @property def user_shared(self): - logger.warning('The parameter "user_shared" is deprecated, use "users_shared" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "user_shared" is deprecated, use "users_shared" instead') return self.users_shared @property @@ -1872,9 +1858,7 @@ def __init__(self, file_id, file_unique_id, duration, performer=None, title=None @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -1969,9 +1953,7 @@ def __init__(self, file_id, file_unique_id, thumbnail=None, file_name=None, mime @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -2035,9 +2017,7 @@ def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=N @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -2087,9 +2067,7 @@ def __init__(self, file_id, file_unique_id, length, duration, thumbnail=None, fi @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -2632,9 +2610,7 @@ class KeyboardButtonRequestUser(KeyboardButtonRequestUsers): def __init__( self, request_id: int, user_is_bot: Optional[bool]=None, user_is_premium: Optional[bool]=None, max_quantity: Optional[int]=None) -> None: - logger.warning('The class "KeyboardButtonRequestUser" is deprecated, use "KeyboardButtonRequestUsers" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The class "KeyboardButtonRequestUser" is deprecated, use "KeyboardButtonRequestUsers" instead') super().__init__(request_id, user_is_bot=user_is_bot, user_is_premium=user_is_premium, max_quantity=max_quantity) @@ -2781,9 +2757,7 @@ def __init__(self, text: str, request_contact: Optional[bool]=None, self.request_chat: Optional[KeyboardButtonRequestChat] = request_chat self.request_users: Optional[KeyboardButtonRequestUsers] = request_users if request_user is not None: - logger.warning('The parameter "request_user" is deprecated, use "request_users" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "request_user" is deprecated, use "request_users" instead') if self.request_users is None: # noinspection PyTypeChecker self.request_users = request_user @@ -3270,9 +3244,7 @@ def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_ed @property def can_manage_voice_chats(self): - logger.warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') return self.can_manage_video_chats @@ -3597,9 +3569,7 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send if kwargs.get("de_json", False) and can_send_media_messages is not None: # Telegram passes can_send_media_messages in Chat.permissions. Temporary created parameter "de_json" allows avoid # deprection warning and individual parameters overriding. - logger.warning('The parameter "can_send_media_messages" is deprecated. Use individual parameters like "can_send_audios", "can_send_documents" etc.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "can_send_media_messages" is deprecated. Use individual parameters like "can_send_audios", "can_send_documents" etc.') self.can_send_audios: Optional[bool] = can_send_media_messages self.can_send_documents: Optional[bool] = can_send_media_messages self.can_send_photos: Optional[bool] = can_send_media_messages @@ -3969,12 +3939,10 @@ def __init__(self, message_text: str, parse_mode: Optional[str] = None, entities self.entities: Optional[List[MessageEntity]] = entities self.link_preview_options: Optional[LinkPreviewOptions] = link_preview_options if disable_web_page_preview is not None: - logger.warning('The parameter "disable_web_page_preview" is deprecated. Use "link_preview_options" instead.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "disable_web_page_preview" is deprecated. Use "link_preview_options" instead.') if link_preview_options: - logger.warning('Both "link_preview_options" and "disable_web_page_preview" parameters are set: conflicting, "disable_web_page_preview" is deprecated') + log_deprecation_warning('Both "link_preview_options" and "disable_web_page_preview" parameters are set: conflicting, "disable_web_page_preview" is deprecated') else: self.link_preview_options: Optional[LinkPreviewOptions] = LinkPreviewOptions(is_disabled=disable_web_page_preview) @@ -4477,23 +4445,17 @@ def __init__(self, id: str, title: str, input_message_content: InputMessageConte @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_width(self) -> int: - logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property def thumb_height(self) -> int: - logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height def to_dict(self): @@ -4584,9 +4546,7 @@ def __init__(self, id: str, photo_url: str, thumbnail_url: str, photo_width: Opt @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url def to_dict(self): @@ -4680,16 +4640,12 @@ def __init__(self, id: str, gif_url: str, thumbnail_url: str, gif_width: Optiona @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_mime_type(self) -> str: - logger.warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') return self.thumbnail_mime_type def to_dict(self): @@ -4784,16 +4740,12 @@ def __init__(self, id: str, mpeg4_url: str, thumbnail_url: str, mpeg4_width: Opt @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_mime_type(self) -> str: - logger.warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_mime_type" is deprecated, use "thumbnail_mime_type" instead') return self.thumbnail_mime_type def to_dict(self): @@ -4894,9 +4846,7 @@ def __init__(self, id: str, video_url: str, mime_type: str, thumbnail_url: str, @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url def to_dict(self): @@ -5113,23 +5063,17 @@ def __init__(self, id: str, title: str, document_url: str, mime_type: str, capti @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_width(self) -> int: - logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property def thumb_height(self) -> int: - logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height def to_dict(self): @@ -5218,23 +5162,17 @@ def __init__(self, id: str, title: str, latitude: float, longitude: float, horiz @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_width(self) -> int: - logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property def thumb_height(self) -> int: - logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height def to_dict(self): @@ -5334,23 +5272,17 @@ def __init__(self, id: str, title: str, latitude: float, longitude: float, addre @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_width(self) -> int: - logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property def thumb_height(self) -> int: - logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height def to_dict(self): @@ -5435,23 +5367,17 @@ def __init__(self, id: str, phone_number: str, first_name: str, last_name: Optio @property def thumb_url(self) -> str: - logger.warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_url" is deprecated, use "thumbnail_url" instead') return self.thumbnail_url @property def thumb_width(self) -> int: - logger.warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_width" is deprecated, use "thumbnail_width" instead') return self.thumbnail_width @property def thumb_height(self) -> int: - logger.warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb_height" is deprecated, use "thumbnail_height" instead') return self.thumbnail_height def to_dict(self): @@ -6139,9 +6065,7 @@ def __init__(self, file_id, file_unique_id, width=None, height=None, duration=No @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6557,30 +6481,22 @@ def __init__(self, name, title, sticker_type, stickers, thumbnail=None, **kwargs @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @property def contains_masks(self) -> bool: - logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type instead"') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "contains_masks" is deprecated, use "sticker_type instead"') return self.sticker_type == 'mask' @property def is_animated(self) -> bool: - logger.warning('The parameter "is_animated" is deprecated since Bot API 7.2. Stickers can now be mixed') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "is_animated" is deprecated since Bot API 7.2. Stickers can now be mixed') return False @property def is_video(self) -> bool: - logger.warning('The parameter "is_video" is deprecated since Bot API 7.2. Stickers can now be mixed') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "is_video" is deprecated since Bot API 7.2. Stickers can now be mixed') return False @@ -6679,9 +6595,7 @@ def __init__(self, file_id, file_unique_id, type, width, height, is_animated, @property def thumb(self) -> Optional[PhotoSize]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail @@ -6899,9 +6813,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail def to_dict(self): @@ -6988,9 +6900,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail def to_dict(self): @@ -7064,9 +6974,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail def to_dict(self): @@ -7129,9 +7037,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, @property def thumb(self) -> Optional[Union[str, Any]]: - logger.warning('The parameter "thumb" is deprecated, use "thumbnail" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "thumb" is deprecated, use "thumbnail" instead') return self.thumbnail def to_dict(self): @@ -7300,9 +7206,7 @@ def __init__( self.is_anonymous: bool = is_anonymous self.type: str = type if poll_type is not None: - logger.warning("Poll: poll_type parameter is deprecated. Use type instead.") - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning("Poll: poll_type parameter is deprecated. Use type instead.") if type is None: self.type: str = poll_type self.allows_multiple_answers: bool = allows_multiple_answers @@ -7545,9 +7449,7 @@ class VoiceChatStarted(VideoChatStarted): """ def __init__(self): - logger.warning('VoiceChatStarted is deprecated. Use VideoChatStarted instead.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('VoiceChatStarted is deprecated. Use VideoChatStarted instead.') super().__init__() @@ -7579,9 +7481,7 @@ class VoiceChatScheduled(VideoChatScheduled): Deprecated, use :class:`VideoChatScheduled` instead. """ def __init__(self, *args, **kwargs): - logger.warning('VoiceChatScheduled is deprecated. Use VideoChatScheduled instead.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('VoiceChatScheduled is deprecated. Use VideoChatScheduled instead.') super().__init__(*args, **kwargs) @@ -7612,9 +7512,7 @@ class VoiceChatEnded(VideoChatEnded): Deprecated, use :class:`VideoChatEnded` instead. """ def __init__(self, *args, **kwargs): - logger.warning('VoiceChatEnded is deprecated. Use VideoChatEnded instead.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('VoiceChatEnded is deprecated. Use VideoChatEnded instead.') super().__init__(*args, **kwargs) @@ -7647,9 +7545,7 @@ class VoiceChatParticipantsInvited(VideoChatParticipantsInvited): Deprecated, use :class:`VideoChatParticipantsInvited` instead. """ def __init__(self, *args, **kwargs): - logger.warning('VoiceChatParticipantsInvited is deprecated. Use VideoChatParticipantsInvited instead.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('VoiceChatParticipantsInvited is deprecated. Use VideoChatParticipantsInvited instead.') super().__init__(*args, **kwargs) @@ -8296,9 +8192,7 @@ def __init__(self, sticker: Union[str, InputFile], emoji_list: List[str], forma self.format: str = format if not self.format: - logger.warning("Deprecation warning. 'format' parameter is required in InputSticker. Setting format to 'static'.") - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning("Deprecation warning. 'format' parameter is required in InputSticker. Setting format to 'static'.") self.format = "static" if service_utils.is_string(self.sticker): @@ -9416,16 +9310,12 @@ def __init__(self, request_id: int, users: List[SharedUser], **kwargs): @property def user_id(self) -> None: - logger.warning('The parameter "user_id" is deprecated, use "user_ids" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "user_id" is deprecated, use "user_ids" instead') return None @property def user_ids(self) -> List[SharedUser]: - logger.warning('The parameter "user_ids" is deprecated, use "users" instead') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning('The parameter "user_ids" is deprecated, use "users" instead') return self.users @@ -9726,9 +9616,7 @@ def __init__(self, chat, message_id, date, **kwargs): @staticmethod def __universal_deprecation(property_name): - logger.warning(f'Deprecation warning: the field "{property_name}" is not accessible for InaccessibleMessage. You should check if your object is Message instance before access.') - if DEPRECATION_STACK_SHOW_DEPTH: - logger.warning("".join(traceback.format_stack(limit=DEPRECATION_STACK_SHOW_DEPTH))) + log_deprecation_warning(f'Deprecation warning: the field "{property_name}" is not accessible for InaccessibleMessage. You should check if your object is Message instance before access.') return None def __getattr__(self, item): From d41e3904b9ba9b154e0a885ff7e13be33dc3860e Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 15 Nov 2024 18:26:39 +0300 Subject: [PATCH 371/480] Version bump and python upgrade --- .github/workflows/setup_python.yml | 2 +- .travis.yml | 2 +- README.md | 2 +- docs/source/conf.py | 2 +- pyproject.toml | 6 +++--- telebot/version.py | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/setup_python.yml b/.github/workflows/setup_python.yml index 670251511..603515ddc 100644 --- a/.github/workflows/setup_python.yml +++ b/.github/workflows/setup_python.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10'] + python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13', 'pypy-3.9', 'pypy-3.10'] name: ${{ matrix.python-version }} and tests steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index 1fe9399d6..cc0a0c62e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: python python: - - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" + - "3.13" - "pypy3" install: "pip install -r requirements.txt" script: diff --git a/README.md b/README.md index 43676d2d1..97d55930d 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ ## Getting started -This API is tested with Python 3.8-3.12 and Pypy 3. +This API is tested with Python 3.9-3.13 and Pypy 3. There are two ways to install the library: * Installation using pip (a Python package manager): diff --git a/docs/source/conf.py b/docs/source/conf.py index 87d25810f..b45dfb263 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.23.0' +release = '4.24.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 07f2ce727..610ced195 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,21 +4,21 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.23.0" +version = "4.24.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.9" keywords = ["telegram", "bot", "api", "tools"] classifiers = [ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Environment :: Console", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)" ] diff --git a/telebot/version.py b/telebot/version.py index bf02d6515..bde2003e4 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.23.0' +__version__ = '4.24.0' From e17a26d1c6c95bdc7aea6695b28b7fc9eec312cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:30:52 +0000 Subject: [PATCH 372/480] Bump werkzeug in /examples/serverless/flask_google_cloud_bot Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.0.3 to 3.0.6. - [Release notes](https://github.com/pallets/werkzeug/releases) - [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/werkzeug/compare/3.0.3...3.0.6) --- updated-dependencies: - dependency-name: werkzeug dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- examples/serverless/flask_google_cloud_bot/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/serverless/flask_google_cloud_bot/requirements.txt b/examples/serverless/flask_google_cloud_bot/requirements.txt index ed0491b0a..e08389a50 100644 --- a/examples/serverless/flask_google_cloud_bot/requirements.txt +++ b/examples/serverless/flask_google_cloud_bot/requirements.txt @@ -1,4 +1,4 @@ pyTelegramBotAPI==4.11.0 Flask==3.0.0 gunicorn==22.0.0 -Werkzeug==3.0.3 +Werkzeug==3.0.6 From ff6db8b947619ee67c62798e7c0e5e968c3ff4df Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 17:08:42 +0400 Subject: [PATCH 373/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 97d55930d..119545779 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From c8d8ec7c2ca8f519c0a60084773d7df344bf8688 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 17:26:25 +0400 Subject: [PATCH 374/480] Added business connection id and subscription period for createinvoicelink --- telebot/__init__.py | 15 +++++++++++++-- telebot/apihelper.py | 6 +++++- telebot/async_telebot.py | 14 ++++++++++++-- telebot/asyncio_helper.py | 6 +++++- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 62cae3f96..04c4d3ced 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5418,7 +5418,9 @@ def create_invoice_link(self, need_shipping_address: Optional[bool]=None, send_phone_number_to_provider: Optional[bool]=None, send_email_to_provider: Optional[bool]=None, - is_flexible: Optional[bool]=None) -> str: + is_flexible: Optional[bool]=None, + subscription_period: Optional[int]=None, + business_connection_id: Optional[str]=None) -> str: """ Use this method to create a link for an invoice. @@ -5427,6 +5429,9 @@ def create_invoice_link(self, Telegram documentation: https://core.telegram.org/bots/api#createinvoicelink + :param business_connection_id: Unique identifier of the business connection on behalf of which the link will be created + :type business_connection_id: :obj:`str` + :param title: Product name, 1-32 characters :type title: :obj:`str` @@ -5449,6 +5454,11 @@ def create_invoice_link(self, (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.) :type prices: :obj:`list` of :obj:`types.LabeledPrice` + :subscription_period: The number of seconds the subscription will be active for before the next payment. + The currency must be set to “XTR” (Telegram Stars) if the parameter is used. Currently, it must always + be 2592000 (30 days) if specified. + :type subscription_period: :obj:`int` + :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency :type max_tip_amount: :obj:`int` @@ -5505,7 +5515,8 @@ def create_invoice_link(self, photo_width=photo_width, photo_height=photo_height, need_name=need_name, need_phone_number=need_phone_number, need_email=need_email, need_shipping_address=need_shipping_address, send_phone_number_to_provider=send_phone_number_to_provider, - send_email_to_provider=send_email_to_provider, is_flexible=is_flexible) + send_email_to_provider=send_email_to_provider, is_flexible=is_flexible ,subscription_period=subscription_period, + business_connection_id=business_connection_id) # noinspection PyShadowingBuiltins diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 92d419c45..43e536e6f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1970,7 +1970,7 @@ def create_invoice_link(token, title, description, payload, provider_token, currency, prices, max_tip_amount=None, suggested_tip_amounts=None, provider_data=None, photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, send_phone_number_to_provider=None, - send_email_to_provider=None, is_flexible=None): + send_email_to_provider=None, is_flexible=None, subscription_period=None, business_connection_id=None): method_url = r'createInvoiceLink' payload = {'title': title, 'description': description, 'payload': payload, 'currency': currency, 'prices': _convert_list_json_serializable(prices)} @@ -2004,6 +2004,10 @@ def create_invoice_link(token, title, description, payload, provider_token, payload['is_flexible'] = is_flexible if provider_token is not None: payload['provider_token'] = provider_token + if subscription_period: + payload['subscription_period'] = subscription_period + if business_connection_id: + payload['business_connection_id'] = business_connection_id return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 75ce41346..61b2dee21 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6836,7 +6836,9 @@ async def create_invoice_link(self, need_shipping_address: Optional[bool]=None, send_phone_number_to_provider: Optional[bool]=None, send_email_to_provider: Optional[bool]=None, - is_flexible: Optional[bool]=None) -> str: + is_flexible: Optional[bool]=None, + subscription_period: Optional[int]=None, + business_connection_id: Optional[str]=None) -> str: """ Use this method to create a link for an invoice. @@ -6844,6 +6846,9 @@ async def create_invoice_link(self, Telegram documentation: https://core.telegram.org/bots/api#createinvoicelink + + :param business_connection_id: Unique identifier of the business connection on behalf of which the link will be created + :type business_connection_id: :obj:`str` :param title: Product name, 1-32 characters :type title: :obj:`str` @@ -6867,6 +6872,11 @@ async def create_invoice_link(self, (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.) :type prices: :obj:`list` of :obj:`types.LabeledPrice` + :subscription_period: The number of seconds the subscription will be active for before the next payment. + The currency must be set to “XTR” (Telegram Stars) if the parameter is used. Currently, it must always + be 2592000 (30 days) if specified. + :type subscription_period: :obj:`int` + :param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency :type max_tip_amount: :obj:`int` @@ -6921,7 +6931,7 @@ async def create_invoice_link(self, currency, prices, max_tip_amount, suggested_tip_amounts, provider_data, photo_url, photo_size, photo_width, photo_height, need_name, need_phone_number, need_email, need_shipping_address, send_phone_number_to_provider, - send_email_to_provider, is_flexible) + send_email_to_provider, is_flexible, subscription_period=subscription_period, business_connection_id=business_connection_id) return result # noinspection PyShadowingBuiltins diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index b21b7f9f0..46b70fe85 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1952,7 +1952,7 @@ async def create_invoice_link(token, title, description, payload, provider_token currency, prices, max_tip_amount=None, suggested_tip_amounts=None, provider_data=None, photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None, need_phone_number=None, need_email=None, need_shipping_address=None, send_phone_number_to_provider=None, - send_email_to_provider=None, is_flexible=None): + send_email_to_provider=None, is_flexible=None, subscription_period=None, business_connection_id=None): method_url = r'createInvoiceLink' payload = {'title': title, 'description': description, 'payload': payload, 'currency': currency, 'prices': await _convert_list_json_serializable(prices)} @@ -1986,6 +1986,10 @@ async def create_invoice_link(token, title, description, payload, provider_token payload['is_flexible'] = is_flexible if provider_token is not None: payload['provider_token'] = provider_token + if subscription_period: + payload['subscription_period'] = subscription_period + if business_connection_id: + payload['business_connection_id'] = business_connection_id return await _process_request(token, method_url, params=payload, method='post') From 90b3c976f542d2a8bd350839834e6f9260966b69 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 17:35:01 +0400 Subject: [PATCH 375/480] Added the fields subscription_expiration_date, is_recurring and is_first_recurring to the class SuccessfulPayment. --- telebot/types.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 66ad984bc..e11e74ecf 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6318,6 +6318,15 @@ class SuccessfulPayment(JsonDeserializable): :param invoice_payload: Bot specified invoice payload :type invoice_payload: :obj:`str` + :param subscription_expiration_date: Optional. Expiration date of the subscription, in Unix time; for recurring payments only + :type subscription_expiration_date: :obj:`int` + + :param is_recurring: Optional. True, if the payment is a recurring payment, false otherwise + :type is_recurring: :obj:`bool` + + :param is_first_recurring: Optional. True, if the payment is the first payment for a subscription + :type is_first_recurring: :obj:`bool` + :param shipping_option_id: Optional. Identifier of the shipping option chosen by the user :type shipping_option_id: :obj:`str` @@ -6341,7 +6350,8 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, currency, total_amount, invoice_payload, shipping_option_id=None, order_info=None, - telegram_payment_charge_id=None, provider_payment_charge_id=None, **kwargs): + telegram_payment_charge_id=None, provider_payment_charge_id=None, + subscription_expiration_date=None, is_recurring=None, is_first_recurring=None, **kwargs): self.currency: str = currency self.total_amount: int = total_amount self.invoice_payload: str = invoice_payload @@ -6349,6 +6359,9 @@ def __init__(self, currency, total_amount, invoice_payload, shipping_option_id=N self.order_info: OrderInfo = order_info self.telegram_payment_charge_id: str = telegram_payment_charge_id self.provider_payment_charge_id: str = provider_payment_charge_id + self.subscription_expiration_date: Optional[int] = subscription_expiration_date + self.is_recurring: Optional[bool] = is_recurring + self.is_first_recurring: Optional[bool] = is_first_recurring # noinspection PyShadowingBuiltins From a12d8c2844c2ac5fecc85e6ae9832ee0aabdce79 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 17:38:42 +0400 Subject: [PATCH 376/480] Added the method editUserStarSubscription. --- telebot/__init__.py | 20 ++++++++++++++++++++ telebot/apihelper.py | 5 +++++ telebot/async_telebot.py | 20 ++++++++++++++++++++ telebot/asyncio_helper.py | 6 ++++++ 4 files changed, 51 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 04c4d3ced..142d71193 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5814,6 +5814,26 @@ def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> """ return apihelper.refund_star_payment(self.token, user_id, telegram_payment_charge_id) + def edit_user_star_subscription(self, user_id: int, telegram_payment_charge_id: str, is_canceled: bool) -> bool: + """ + Allows the bot to cancel or re-enable extension of a subscription paid in Telegram Stars. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#edituserstarsubscription + + :param user_id: Identifier of the user whose subscription will be edited + :type user_id: :obj:`int` + + :param telegram_payment_charge_id: Telegram payment identifier for the subscription + :type telegram_payment_charge_id: :obj:`str` + + :param is_canceled: Pass True to cancel extension of the user subscription; the subscription must be active up to the end of the current subscription period. Pass False to allow the user to re-enable a subscription that was previously canceled by the bot. + :type is_canceled: :obj:`bool` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + return apihelper.edit_user_star_subscription(self.token, user_id, telegram_payment_charge_id, is_canceled) + def edit_message_caption( self, caption: str, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 43e536e6f..69fa5bf4f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1805,6 +1805,11 @@ def refund_star_payment(token, user_id, telegram_payment_charge_id): payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id} return _make_request(token, method_url, params=payload) +def edit_user_star_subscription(token, user_id, telegram_payment_charge_id, is_canceled): + method_url = 'editUserStarSubscription' + payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id, 'is_canceled': is_canceled} + return _make_request(token, method_url, params=payload) + def unpin_all_general_forum_topic_messages(token, chat_id): method_url = 'unpinAllGeneralForumTopicMessages' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 61b2dee21..f82c7238e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7220,6 +7220,26 @@ async def refund_star_payment(self, user_id: int, telegram_payment_charge_id: st """ return await asyncio_helper.refund_star_payment(self.token, user_id, telegram_payment_charge_id) + async def edit_user_star_subscription(self, user_id: int, telegram_payment_charge_id: str, is_canceled: bool) -> bool: + """ + Allows the bot to cancel or re-enable extension of a subscription paid in Telegram Stars. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#edituserstarsubscription + + :param user_id: Identifier of the user whose subscription will be edited + :type user_id: :obj:`int` + + :param telegram_payment_charge_id: Telegram payment identifier for the subscription + :type telegram_payment_charge_id: :obj:`str` + + :param is_canceled: Pass True to cancel extension of the user subscription; the subscription must be active up to the end of the current subscription period. Pass False to allow the user to re-enable a subscription that was previously canceled by the bot. + :type is_canceled: :obj:`bool` + + :return: On success, True is returned. + :rtype: :obj:`bool` + """ + return await asyncio_helper.edit_user_star_subscription(self.token, user_id, telegram_payment_charge_id, is_canceled) + async def edit_message_caption( self, caption: str, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 46b70fe85..3e1a68a1d 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1793,6 +1793,12 @@ async def refund_star_payment(token, user_id, telegram_payment_charge_id): return await _process_request(token, method_url, params=payload) +async def edit_user_star_subscription(token, user_id, telegram_payment_charge_id, is_canceled): + method_url = 'editUserStarSubscription' + payload = {'user_id': user_id, 'telegram_payment_charge_id': telegram_payment_charge_id, 'is_canceled': is_canceled} + return await _process_request(token, method_url, params=payload) + + async def unpin_all_general_forum_topic_messages(token, chat_id): method_url = 'unpinAllGeneralForumTopicMessages' payload = {'chat_id': chat_id} From 8eb5d1065b2cd2712430bb7928806919edf6e961 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 17:40:04 +0400 Subject: [PATCH 377/480] Added the field subscription_period to the class TransactionPartnerUser. --- telebot/types.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index e11e74ecf..76cf20b61 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10489,6 +10489,9 @@ class TransactionPartnerUser(TransactionPartner): :param invoice_payload: Optional, Bot-specified invoice payload :type invoice_payload: :obj:`str` + :param subscription_period: Optional. The duration of the paid subscription + :type subscription_period: :obj:`int` + :param paid_media: Optional. Information about the paid media bought by the user :type paid_media: :obj:`list` of :class:`PaidMedia` @@ -10496,11 +10499,13 @@ class TransactionPartnerUser(TransactionPartner): :rtype: :class:`TransactionPartnerUser` """ - def __init__(self, type, user, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, **kwargs): + def __init__(self, type, user, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, + subscription_period=None, **kwargs): self.type: str = type self.user: User = user self.invoice_payload: Optional[str] = invoice_payload self.paid_media: Optional[List[PaidMedia]] = paid_media + self.subscription_period: Optional[int] = subscription_period @classmethod def de_json(cls, json_string): From e55b0971f65f74738c17d264291398da178101a5 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 18:01:48 +0400 Subject: [PATCH 378/480] Added the method setUserEmojiStatus. The user must allow the bot to manage their emoji status. --- telebot/__init__.py | 20 ++++++++++++++++++++ telebot/apihelper.py | 10 ++++++++++ telebot/async_telebot.py | 20 ++++++++++++++++++++ telebot/asyncio_helper.py | 10 ++++++++++ 4 files changed, 60 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 142d71193..494c0ec5d 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1512,6 +1512,26 @@ def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, apihelper.get_user_profile_photos(self.token, user_id, offset=offset, limit=limit) ) + def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Optional[str]=None, emoji_status_expiration_date: Optional[int]=None) -> bool: + """ + Changes the emoji status for a given user that previously allowed the bot to manage their emoji status via the Mini App method requestEmojiStatusAccess. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setuseremojistatus + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param emoji_status_custom_emoji_id: Custom emoji identifier of the emoji status to set. Pass an empty string to remove the status. + :type emoji_status_custom_emoji_id: :obj:`str` + + :param emoji_status_expiration_date: Expiration date of the emoji status, if any + :type emoji_status_expiration_date: :obj:`int` + + :return: :obj:`bool` + """ + return apihelper.set_user_emoji_status( + self.token, user_id, emoji_status_custom_emoji_id=emoji_status_custom_emoji_id, emoji_status_expiration_date=emoji_status_expiration_date) + def get_chat(self, chat_id: Union[int, str]) -> types.ChatFullInfo: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 69fa5bf4f..68623922f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -341,6 +341,16 @@ def get_user_profile_photos(token, user_id, offset=None, limit=None): payload['limit'] = limit return _make_request(token, method_url, params=payload) + +def set_user_emoji_status(token, user_id, emoji_status_custom_emoji_id=None, emoji_status_expiration_date=None): + method_url = r'setUserEmojiStatus' + payload = {'user_id': user_id} + if emoji_status_custom_emoji_id: + payload['emoji_status_custom_emoji_id'] = emoji_status_custom_emoji_id + if emoji_status_expiration_date: + payload['emoji_status_expiration_date'] = emoji_status_expiration_date + return _make_request(token, method_url, params=payload) + def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None): method_url = r'setMessageReaction' payload = {'chat_id': chat_id, 'message_id': message_id} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index f82c7238e..6ab489756 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -2987,6 +2987,26 @@ async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None """ result = await asyncio_helper.get_user_profile_photos(self.token, user_id, offset, limit) return types.UserProfilePhotos.de_json(result) + + async def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Optional[str]=None, emoji_status_expiration_date: Optional[int]=None) -> bool: + """ + Use this method to change the emoji status for a given user that previously allowed the bot to manage their emoji status via the Mini App method requestEmojiStatusAccess. + + Telegram documentation: https://core.telegram.org/bots/api#setuseremojistatus + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param emoji_status_custom_emoji_id: Custom emoji identifier of the emoji status to set. Pass an empty string to remove the status. + :type emoji_status_custom_emoji_id: :obj:`str`, optional + + :param emoji_status_expiration_date: Expiration date of the emoji status, if any + :type emoji_status_expiration_date: :obj:`int`, optional + + :return: :obj:`bool` + """ + result = await asyncio_helper.set_user_emoji_status(self.token, user_id, emoji_status_custom_emoji_id, emoji_status_expiration_date) + return result async def get_chat(self, chat_id: Union[int, str]) -> types.ChatFullInfo: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 3e1a68a1d..41d94d0bd 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -325,6 +325,16 @@ async def get_user_profile_photos(token, user_id, offset=None, limit=None): payload['limit'] = limit return await _process_request(token, method_url, params=payload) + +async def set_user_emoji_status(token, user_id, emoji_status_custom_emoji_id=None, emoji_status_expiration_date=None): + method_url = r'setUserEmojiStatus' + payload = {'user_id': user_id} + if emoji_status_custom_emoji_id: + payload['emoji_status_custom_emoji_id'] = emoji_status_custom_emoji_id + if emoji_status_expiration_date: + payload['emoji_status_expiration_date'] = emoji_status_expiration_date + return await _process_request(token, method_url, params=payload) + async def set_message_reaction(token, chat_id, message_id, reaction=None, is_big=None): method_url = r'setMessageReaction' payload = {'chat_id': chat_id, 'message_id': message_id} From bee6bab8213e1d22731146b9e92245fd1a42cdb5 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 18:10:08 +0400 Subject: [PATCH 379/480] Added the class PreparedInlineMessage and the method savePreparedInlineMessage, allowing bots to suggest users to send a specific message from a Mini App via the method shareMessage. --- telebot/__init__.py | 36 ++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 15 +++++++++++++++ telebot/async_telebot.py | 30 ++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 14 ++++++++++++++ telebot/types.py | 28 ++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 494c0ec5d..586f44c9a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6769,6 +6769,42 @@ def answer_web_app_query(self, web_app_query_id: str, result: types.InlineQueryR """ return apihelper.answer_web_app_query(self.token, web_app_query_id, result) + def save_prepared_inline_message( + self, user_id: int, result: types.InlineQueryResultBase, allow_user_chats: Optional[bool]=None, + allow_bot_chats: Optional[bool]=None, allow_group_chats: Optional[bool]=None, + allow_channel_chats: Optional[bool]=None) -> types.PreparedInlineMessage: + """ + Use this method to store a message that can be sent by a user of a Mini App. + Returns a PreparedInlineMessage object. + + Telegram Documentation: https://core.telegram.org/bots/api#savepreparedinlinemessage + + :param user_id: Unique identifier of the target user that can use the prepared message + :type user_id: :obj:`int` + + :param result: A JSON-serialized object describing the message to be sent + :type result: :class:`telebot.types.InlineQueryResultBase` + + :param allow_user_chats: Pass True if the message can be sent to private chats with users + :type allow_user_chats: :obj:`bool` + + :param allow_bot_chats: Pass True if the message can be sent to private chats with bots + :type allow_bot_chats: :obj:`bool` + + :param allow_group_chats: Pass True if the message can be sent to group and supergroup chats + :type allow_group_chats: :obj:`bool` + + :param allow_channel_chats: Pass True if the message can be sent to channel chats + :type allow_channel_chats: :obj:`bool` + + :return: On success, a PreparedInlineMessage object is returned. + :rtype: :class:`telebot.types.PreparedInlineMessage` + """ + return types.PreparedInlineMessage.de_json( + apihelper.save_prepared_inline_message( + self.token, user_id, result, allow_user_chats=allow_user_chats, allow_bot_chats=allow_bot_chats, + allow_group_chats=allow_group_chats, allow_channel_chats=allow_channel_chats) + ) def register_for_reply(self, message: types.Message, callback: Callable, *args, **kwargs) -> None: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 68623922f..01a1a77ba 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1981,6 +1981,21 @@ def answer_web_app_query(token, web_app_query_id, result: types.InlineQueryResul return _make_request(token, method_url, params=payload, method='post') +def save_prepared_inline_message(token, user_id, result: types.InlineQueryResultBase, allow_user_chats=None, + allow_bot_chats=None, allow_group_chats=None, allow_channel_chats=None): + method_url = 'savePreparedInlineMessage' + payload = {'user_id': user_id, 'result': result.to_json()} + if allow_user_chats is not None: + payload['allow_user_chats'] = allow_user_chats + if allow_bot_chats is not None: + payload['allow_bot_chats'] = allow_bot_chats + if allow_group_chats is not None: + payload['allow_group_chats'] = allow_group_chats + if allow_channel_chats is not None: + payload['allow_channel_chats'] = allow_channel_chats + return _make_request(token, method_url, params=payload, method='post') + + def create_invoice_link(token, title, description, payload, provider_token, currency, prices, max_tip_amount=None, suggested_tip_amounts=None, provider_data=None, photo_url=None, photo_size=None, photo_width=None, photo_height=None, need_name=None, need_phone_number=None, diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 6ab489756..659596f59 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3148,6 +3148,36 @@ async def answer_web_app_query(self, web_app_query_id: str, result: types.Inline return await asyncio_helper.answer_web_app_query(self.token, web_app_query_id, result) + async def save_prepared_inline_message(self, user_id: int, result: types.InlineQueryResultBase, allow_user_chats: Optional[bool]=None, + allow_bot_chats: Optional[bool]=None, allow_group_chats: Optional[bool]=None, allow_channel_chats: Optional[bool]=None) -> types.PreparedInlineMessage: + """ + Stores a message that can be sent by a user of a Mini App. Returns a PreparedInlineMessage object. + + Telegram Documentation: https://core.telegram.org/bots/api#savepreparedinlinemessage + + :param user_id: Unique identifier of the target user that can use the prepared message + :type user_id: :obj:`int` + + :param result: A JSON-serialized object describing the message to be sent + :type result: :class:`telebot.types.InlineQueryResultBase` + + :param allow_user_chats: Pass True if the message can be sent to private chats with users + :type allow_user_chats: :obj:`bool`, optional + + :param allow_bot_chats: Pass True if the message can be sent to private chats with bots + :type allow_bot_chats: :obj:`bool`, optional + + :param allow_group_chats: Pass True if the message can be sent to group and supergroup chats + :type allow_group_chats: :obj:`bool`, optional + + :param allow_channel_chats: Pass True if the message can be sent to channel chats + :type allow_channel_chats: :obj:`bool`, optional + + :return: :class:`telebot.types.PreparedInlineMessage` + """ + result = await asyncio_helper.save_prepared_inline_message(self.token, user_id, result, allow_user_chats, allow_bot_chats, allow_group_chats, allow_channel_chats) + return types.PreparedInlineMessage.de_json(result) + async def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatMember: """ Use this method to get information about a member of a chat. Returns a ChatMember object on success. diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 41d94d0bd..4523e7173 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -406,6 +406,20 @@ async def answer_web_app_query(token, web_app_query_id, result: types.InlineQuer return await _process_request(token, method_url, params=payload, method='post') +async def save_prepared_inline_message(token, user_id, result: types.InlineQueryResultBase, allow_user_chats=None, allow_bot_chats=None, allow_group_chats=None, allow_channel_chats=None): + method_url = r'savePreparedInlineMessage' + payload = {'user_id': user_id, 'result': result.to_json()} + if allow_user_chats is not None: + payload['allow_user_chats'] = allow_user_chats + if allow_bot_chats is not None: + payload['allow_bot_chats'] = allow_bot_chats + if allow_group_chats is not None: + payload['allow_group_chats'] = allow_group_chats + if allow_channel_chats is not None: + payload['allow_channel_chats'] = allow_channel_chats + return await _process_request(token, method_url, params=payload) + + async def get_chat_member(token, chat_id, user_id): method_url = r'getChatMember' payload = {'chat_id': chat_id, 'user_id': user_id} diff --git a/telebot/types.py b/telebot/types.py index 76cf20b61..904379dbc 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10997,3 +10997,31 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) + + +class PreparedInlineMessage(JsonDeserializable): + """ + Describes an inline message to be sent by a user of a Mini App. + + Telegram documentation: https://core.telegram.org/bots/api#preparedinlinemessage + + :param id: Unique identifier of the prepared message + :type id: :obj:`str` + + :param expiration_date: Expiration date of the prepared message, in Unix time. Expired prepared messages can no longer be used + :type expiration_date: :obj:`int` + + :return: Instance of the class + :rtype: :class:`PreparedInlineMessage` + """ + + def __init__(self, id, expiration_date, **kwargs): + self.id: str = id + self.expiration_date: int = expiration_date + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + From 3d740ffd97364ec5fd81c3eb3bba47d356500f60 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 18:18:37 +0400 Subject: [PATCH 380/480] Added the classes Gift and Gifts and the method getAvailableGifts, allowing bots to get all gifts available for sending. --- telebot/__init__.py | 12 ++++++++ telebot/apihelper.py | 5 ++++ telebot/async_telebot.py | 12 ++++++++ telebot/asyncio_helper.py | 4 +++ telebot/types.py | 63 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 586f44c9a..a274d2272 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6249,7 +6249,19 @@ def delete_sticker_set(self, name:str) -> bool: :rtype: :obj:`bool` """ return apihelper.delete_sticker_set(self.token, name) + + def get_available_gifts(self) -> types.Gifts: + """ + Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. + + Telegram documentation: https://core.telegram.org/bots/api#getavailablegifts + :return: On success, a Gifts object is returned. + :rtype: :class:`telebot.types.Gifts` + """ + return types.Gifts.de_json( + apihelper.get_available_gifts(self.token) + ) def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, sticker: types.InputSticker) -> bool: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 01a1a77ba..83606f746 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1924,6 +1924,11 @@ def delete_sticker_set(token, name): return _make_request(token, method_url, params=payload, method='post') +def get_available_gifts(token): + method_url = 'getAvailableGifts' + return _make_request(token, method_url) + + def set_sticker_emoji_list(token, sticker, emoji_list): method_url = 'setStickerEmojiList' payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 659596f59..60719477d 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7707,6 +7707,18 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) + async def get_available_gifts(self) -> types.Gifts: + """ + Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. + + Telegram documentation: https://core.telegram.org/bots/api#getavailablegifts + + :return: On success, a Gifts object is returned. + :rtype: :class:`telebot.types.Gifts` + """ + + return types.Gifts.de_json(await asyncio_helper.get_available_gifts(self.token)) + async def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, sticker: types.InputSticker) -> bool: """ Use this method to replace an existing sticker in a sticker set with a new one. The method is equivalent to calling deleteStickerFromSet, then addStickerToSet, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 4523e7173..47a1da1dc 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1916,6 +1916,10 @@ async def delete_sticker_set(token, name): payload = {'name': name} return await _process_request(token, method_url, params=payload, method='post') +async def get_available_gifts(token): + method_url = 'getAvailableGifts' + return await _process_request(token, method_url) + async def set_custom_emoji_sticker_set_thumbnail(token, name, custom_emoji_id=None): method_url = 'setCustomEmojiStickerSetThumbnail' payload = {'name': name} diff --git a/telebot/types.py b/telebot/types.py index 904379dbc..c6386a61b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11025,3 +11025,66 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) + +class Gift(JsonDeserializable): + """ + This object represents a gift that can be sent by the bot. + + Telegram documentation: https://core.telegram.org/bots/api#gift + + :param id: Unique identifier of the gift + :type id: :obj:`str` + + :param sticker: The sticker that represents the gift + :type sticker: :class:`Sticker` + + :param star_count: The number of Telegram Stars that must be paid to send the sticker + :type star_count: :obj:`int` + + :param total_count: Optional. The total number of the gifts of this type that can be sent; for limited gifts only + :type total_count: :obj:`int` + + :param remaining_count: Optional. The number of remaining gifts of this type that can be sent; for limited gifts only + :type remaining_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`Gift` + """ + + def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, **kwargs): + self.id: str = id + self.sticker: Sticker = sticker + self.star_count: int = star_count + self.total_count: Optional[int] = total_count + self.remaining_count: Optional[int] = remaining_count + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['sticker'] = Sticker.de_json(obj['sticker']) + return cls(**obj) + +class Gifts(JsonDeserializable): + """ + This object represent a list of gifts. + + Telegram documentation: https://core.telegram.org/bots/api#gifts + + :param gifts: The list of gifts + :type gifts: :obj:`list` of :class:`Gift` + + :return: Instance of the class + :rtype: :class:`Gifts` + """ + + def __init__(self, gifts, **kwargs): + self.gifts: List[Gift] = gifts + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['gifts'] = [Gift.de_json(gift) for gift in obj['gifts']] + return cls(**obj) + \ No newline at end of file From a2d2a86d4f496babff9353bf672222c773bbe5be Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 18:22:31 +0400 Subject: [PATCH 381/480] Added the method sendGift, allowing bots to send gifts to users. --- telebot/__init__.py | 26 ++++++++++++++++++++++++++ telebot/apihelper.py | 11 +++++++++++ telebot/async_telebot.py | 26 ++++++++++++++++++++++++++ telebot/asyncio_helper.py | 11 +++++++++++ 4 files changed, 74 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index a274d2272..bb33f55b5 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6249,6 +6249,32 @@ def delete_sticker_set(self, name:str) -> bool: :rtype: :obj:`bool` """ return apihelper.delete_sticker_set(self.token, name) + + def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + """ + Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#sendgift + + :param user_id: Unique identifier of the target user that will receive the gift + :type user_id: :obj:`int` + + :param gift_id: Identifier of the gift + :type gift_id: :obj:`str` + + :param text: Text that will be shown along with the gift; 0-255 characters + :type text: :obj:`str` + + :param text_parse_mode: Mode for parsing entities in the text. See formatting options for more details. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_parse_mode: :obj:`str` + + :param text_entities: A JSON-serialized list of special entities that appear in the gift text. It can be specified instead of text_parse_mode. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_entities: :obj:`list` of :obj:`types.MessageEntity` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 83606f746..5ea37c4fd 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1929,6 +1929,17 @@ def get_available_gifts(token): return _make_request(token, method_url) +def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None): + method_url = 'sendGift' + payload = {'user_id': user_id, 'gift_id': gift_id} + if text: + payload['text'] = text + if text_parse_mode: + payload['text_parse_mode'] = text_parse_mode + if text_entities: + payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + return _make_request(token, method_url, params=payload, method='post') + def set_sticker_emoji_list(token, sticker, emoji_list): method_url = 'setStickerEmojiList' payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 60719477d..7f50b1c86 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7706,6 +7706,32 @@ async def delete_sticker_set(self, name:str) -> bool: """ return await asyncio_helper.delete_sticker_set(self.token, name) + + async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + """ + Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#sendgift + + :param user_id: Unique identifier of the target user that will receive the gift + :type user_id: :obj:`int` + + :param gift_id: Identifier of the gift + :type gift_id: :obj:`str` + + :param text: Text that will be shown along with the gift; 0-255 characters + :type text: :obj:`str` + + :param text_parse_mode: Mode for parsing entities in the text. See formatting options for more details. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_parse_mode: :obj:`str` + + :param text_entities: A JSON-serialized list of special entities that appear in the gift text. It can be specified instead of text_parse_mode. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_entities: :obj:`list` of :obj:`types.MessageEntity` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 47a1da1dc..56604c750 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1916,6 +1916,17 @@ async def delete_sticker_set(token, name): payload = {'name': name} return await _process_request(token, method_url, params=payload, method='post') +async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None): + method_url = 'sendGift' + payload = {'user_id': user_id, 'gift_id': gift_id} + if text: + payload['text'] = text + if text_parse_mode: + payload['text_parse_mode'] = text_parse_mode + if text_entities: + payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + return await _process_request(token, method_url, params=payload, method='post') + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) From 9c7c47f3628f5997949f456b52aa18cb624832ff Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Nov 2024 18:23:46 +0400 Subject: [PATCH 382/480] Added the field gift to the class TransactionPartnerUser. --- telebot/types.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index c6386a61b..3a71887de 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10495,17 +10495,21 @@ class TransactionPartnerUser(TransactionPartner): :param paid_media: Optional. Information about the paid media bought by the user :type paid_media: :obj:`list` of :class:`PaidMedia` + :param gift: Optional. The gift sent to the user by the bot + :type gift: :class:`Gift` + :return: Instance of the class :rtype: :class:`TransactionPartnerUser` """ def __init__(self, type, user, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, - subscription_period=None, **kwargs): + subscription_period=None, gift: Optional[Gift] = None, **kwargs): self.type: str = type self.user: User = user self.invoice_payload: Optional[str] = invoice_payload self.paid_media: Optional[List[PaidMedia]] = paid_media self.subscription_period: Optional[int] = subscription_period + self.gift: Optional[Gift] = gift @classmethod def de_json(cls, json_string): @@ -10514,6 +10518,8 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj['user']) if 'paid_media' in obj: obj['paid_media'] = [PaidMedia.de_json(media) for media in obj['paid_media']] + if 'gift' in obj: + obj['gift'] = Gift.de_json(obj['gift']) return cls(**obj) @@ -11025,7 +11031,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - + class Gift(JsonDeserializable): """ This object represents a gift that can be sent by the bot. From e57136d6d72aec1b8af29ea11a026a6a1c8b8229 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:27:29 +0000 Subject: [PATCH 383/480] Bump aiohttp from 3.10.2 to 3.10.11 Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.10.2 to 3.10.11. - [Release notes](https://github.com/aio-libs/aiohttp/releases) - [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst) - [Commits](https://github.com/aio-libs/aiohttp/compare/v3.10.2...v3.10.11) --- updated-dependencies: - dependency-name: aiohttp dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2abfd54bd..55dd7e486 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest requests==2.32.0 wheel==0.38.1 -aiohttp==3.10.2 +aiohttp==3.10.11 From f9c857fe60724140ec9f5453f363e4fa69e3134d Mon Sep 17 00:00:00 2001 From: Andy Kluger Date: Tue, 26 Nov 2024 12:07:24 -0500 Subject: [PATCH 384/480] Update colorcodebot description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 119545779..eb59d8a74 100644 --- a/README.md +++ b/README.md @@ -830,7 +830,7 @@ Here are some examples of template: * [RadRetroRobot](https://github.com/Tronikart/RadRetroRobot) by *Tronikart* - Multifunctional Telegram Bot RadRetroRobot. * [League of Legends bot](https://telegram.me/League_of_Legends_bot) ([source](https://github.com/i32ropie/lol)) by *i32ropie* * [NeoBot](https://github.com/neoranger/NeoBot) by [@NeoRanger](https://github.com/neoranger) -* [ColorCodeBot](https://t.me/colorcodebot) ([source](https://github.com/andydecleyre/colorcodebot)) - Share code snippets as beautifully syntax-highlighted HTML and/or images. +* [ColorCodeBot](https://t.me/colorcodebot) ([source](https://github.com/andydecleyre/colorcodebot)) - Share code snippets as beautifully syntax-highlighted images. * [ComedoresUGRbot](http://telegram.me/ComedoresUGRbot) ([source](https://github.com/alejandrocq/ComedoresUGRbot)) by [*alejandrocq*](https://github.com/alejandrocq) - Telegram bot to check the menu of Universidad de Granada dining hall. * [proxybot](https://github.com/p-hash/proxybot) - Simple Proxy Bot for Telegram. by p-hash * [DonantesMalagaBot](https://github.com/vfranch/DonantesMalagaBot) - DonantesMalagaBot facilitates information to Malaga blood donors about the places where they can donate today or in the incoming days. It also records the date of the last donation so that it helps the donors to know when they can donate again. - by vfranch From 73c68c13bf7eba3e2364e3c0dd70b0495fa1f1c6 Mon Sep 17 00:00:00 2001 From: Samorezov V Date: Fri, 29 Nov 2024 22:45:08 +0300 Subject: [PATCH 385/480] Fix: change code for non-escape mode - return url --- telebot/formatting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index 24299b51a..801a67ec1 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -240,7 +240,7 @@ def mlink(content: str, url: str, escape: Optional[bool]=True) -> str: :return: The formatted string. :rtype: :obj:`str` """ - return '[{}]({})'.format(escape_markdown(content), escape_markdown(url) if escape else content) + return '[{}]({})'.format(escape_markdown(content), escape_markdown(url) if escape else url) def hlink(content: str, url: str, escape: Optional[bool]=True) -> str: From b089ae1e744ff417b44d39c63596c43831ba2be7 Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 4 Dec 2024 17:48:01 +0400 Subject: [PATCH 386/480] bot api 8.1 --- telebot/types.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 3a71887de..119e14a53 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10411,6 +10411,8 @@ def de_json(cls, json_string): return TransactionPartnerTelegramAds.de_json(obj) elif obj["type"] == "telegram_api": return TransactionPartnerTelegramApi.de_json(obj) + elif obj["type"] == "affiliate_program": + return TransactionPartnerAffiliateProgram.de_json(obj) elif obj["type"] == "other": return TransactionPartnerOther.de_json(obj) @@ -10486,6 +10488,9 @@ class TransactionPartnerUser(TransactionPartner): :param user: Information about the user :type user: :class:`User` + :param affiliate: Optional. Information about the affiliate that received a commission via this transaction + :type affiliate: :class:`AffiliateInfo` + :param invoice_payload: Optional, Bot-specified invoice payload :type invoice_payload: :obj:`str` @@ -10502,10 +10507,11 @@ class TransactionPartnerUser(TransactionPartner): :rtype: :class:`TransactionPartnerUser` """ - def __init__(self, type, user, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, + def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, subscription_period=None, gift: Optional[Gift] = None, **kwargs): self.type: str = type self.user: User = user + self.affiliate: Optional[AffiliateInfo] = affiliate self.invoice_payload: Optional[str] = invoice_payload self.paid_media: Optional[List[PaidMedia]] = paid_media self.subscription_period: Optional[int] = subscription_period @@ -10584,6 +10590,9 @@ class StarTransaction(JsonDeserializable): :param amount: Number of Telegram Stars transferred by the transaction :type amount: :obj:`int` + :param nanostar_amount: Optional. The number of 1/1000000000 shares of Telegram Stars transferred by the transaction; from 0 to 999999999 + :type nanostar_amount: :obj:`int` + :param date: Date the transaction was created in Unix time :type date: :obj:`int` @@ -10607,12 +10616,13 @@ def de_json(cls, json_string): obj['receiver'] = TransactionPartner.de_json(obj['receiver']) return cls(**obj) - def __init__(self, id, amount, date, source=None, receiver=None, **kwargs): + def __init__(self, id, amount, date, source=None, receiver=None, nanostar_amount=None, **kwargs): self.id: str = id self.amount: int = amount self.date: int = date self.source: Optional[TransactionPartner] = source self.receiver: Optional[TransactionPartner] = receiver + self.nanostar_amount: Optional[int] = nanostar_amount class StarTransactions(JsonDeserializable): @@ -11093,4 +11103,82 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['gifts'] = [Gift.de_json(gift) for gift in obj['gifts']] return cls(**obj) - \ No newline at end of file + + +class TransactionPartnerAffiliateProgram(TransactionPartner): + """ + Describes the affiliate program that issued the affiliate commission received via this transaction. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartneraffiliateprogram + + :param type: Type of the transaction partner, always “affiliate_program” + :type type: :obj:`str` + + :param sponsor_user: Optional. Information about the bot that sponsored the affiliate program + :type sponsor_user: :class:`User` + + :param commission_per_mille: The number of Telegram Stars received by the bot for each 1000 Telegram Stars received by the affiliate program sponsor from referred users + :type commission_per_mille: :obj:`int` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerAffiliateProgram` + """ + + def __init__(self, type, commission_per_mille, sponsor_user=None, **kwargs): + self.type: str = type + self.sponsor_user: Optional[User] = sponsor_user + self.commission_per_mille: int = commission_per_mille + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'sponsor_user' in obj: + obj['sponsor_user'] = User.de_json(obj['sponsor_user']) + + return cls(**obj) + + +class AffiliateInfo(JsonDeserializable): + """ + Contains information about the affiliate that received a commission via this transaction. + + Telegram documentation: https://core.telegram.org/bots/api#affiliateinfo + + :param affiliate_user: Optional. The bot or the user that received an affiliate commission if it was received by a bot or a user + :type affiliate_user: :class:`User` + + :param affiliate_chat: Optional. The chat that received an affiliate commission if it was received by a chat + :type affiliate_chat: :class:`Chat` + + :param commission_per_mille: The number of Telegram Stars received by the affiliate for each 1000 Telegram Stars received by the bot from referred users + :type commission_per_mille: :obj:`int` + + :param amount: Integer amount of Telegram Stars received by the affiliate from the transaction, rounded to 0; can be negative for refunds + :type amount: :obj:`int` + + :param nanostar_amount: Optional. The number of 1/1000000000 shares of Telegram Stars received by the affiliate; from -999999999 to 999999999; can be negative for refunds + :type nanostar_amount: :obj:`int` + + :return: Instance of the class + :rtype: :class:`AffiliateInfo` + """ + + def __init__(self, commission_per_mille, amount, affiliate_user=None, affiliate_chat=None, nanostar_amount=None, **kwargs): + self.affiliate_user: Optional[User] = affiliate_user + self.affiliate_chat: Optional[Chat] = affiliate_chat + self.commission_per_mille: int = commission_per_mille + self.amount: int = amount + self.nanostar_amount: Optional[int] = nanostar_amount + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'affiliate_user' in obj: + obj['affiliate_user'] = User.de_json(obj['affiliate_user']) + if 'affiliate_chat' in obj: + obj['affiliate_chat'] = Chat.de_json(obj['affiliate_chat']) + return cls(**obj) + + From e73703f3c11c842284aa7efc737c93786349a0ce Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 4 Dec 2024 17:49:09 +0400 Subject: [PATCH 387/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb59d8a74..bbc6f1698 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From 15b03428de769044581115b51b9fbe79969b1d72 Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 4 Dec 2024 18:14:39 +0400 Subject: [PATCH 388/480] fix --- telebot/types.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 119e14a53..e4dafaa7d 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10526,6 +10526,8 @@ def de_json(cls, json_string): obj['paid_media'] = [PaidMedia.de_json(media) for media in obj['paid_media']] if 'gift' in obj: obj['gift'] = Gift.de_json(obj['gift']) + if 'affiliate' in obj: + obj['affiliate'] = AffiliateInfo.de_json(obj['affiliate']) return cls(**obj) From beef0e6d7b8692fb6f3f1a0eea93d1520efe3cf0 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 4 Dec 2024 17:43:21 +0300 Subject: [PATCH 389/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b45dfb263..fb559d15e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.24.0' +release = '4.25.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 610ced195..ebb66f1c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.24.0" +version = "4.25.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index bde2003e4..9317bd5d7 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.24.0' +__version__ = '4.25.0' From 6ecfd1b00ce8135bf7a0194e3c39c745590b18ed Mon Sep 17 00:00:00 2001 From: Heck Lawert Date: Mon, 9 Dec 2024 10:02:49 +0100 Subject: [PATCH 390/480] Fix issue with thumbnail in InputMedia types --- telebot/apihelper.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 5ea37c4fd..3044b226d 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2271,6 +2271,12 @@ def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media + if 'thumbnail' in media_dict: + thumbnail = media_dict['thumbnail'] + if isinstance(thumbnail, types.InputFile): + thumbnail_key = 'thumbnail_' + key + files[thumbnail_key] = thumbnail + media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files From 4cc438abe6c161dc22f1ad2937fc7200cfe06abb Mon Sep 17 00:00:00 2001 From: Daniil Gilmutdinov Date: Tue, 10 Dec 2024 23:17:43 +0500 Subject: [PATCH 391/480] Fixed typo in method params --- telebot/__init__.py | 2 +- telebot/async_telebot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index bb33f55b5..51eb63d4a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5474,7 +5474,7 @@ def create_invoice_link(self, (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.) :type prices: :obj:`list` of :obj:`types.LabeledPrice` - :subscription_period: The number of seconds the subscription will be active for before the next payment. + :param subscription_period: The number of seconds the subscription will be active for before the next payment. The currency must be set to “XTR” (Telegram Stars) if the parameter is used. Currently, it must always be 2592000 (30 days) if specified. :type subscription_period: :obj:`int` diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 7f50b1c86..0e298ace7 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -6922,7 +6922,7 @@ async def create_invoice_link(self, (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.) :type prices: :obj:`list` of :obj:`types.LabeledPrice` - :subscription_period: The number of seconds the subscription will be active for before the next payment. + :param subscription_period: The number of seconds the subscription will be active for before the next payment. The currency must be set to “XTR” (Telegram Stars) if the parameter is used. Currently, it must always be 2592000 (30 days) if specified. :type subscription_period: :obj:`int` From 63ddb1537f760027043d225ef540ab49a8013728 Mon Sep 17 00:00:00 2001 From: Heck Lawert Date: Thu, 12 Dec 2024 16:09:23 +0100 Subject: [PATCH 392/480] Fix issue with thumbnail in InputMedia types --- telebot/asyncio_helper.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 56604c750..d11245d56 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2243,6 +2243,12 @@ async def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media + if 'thumbnail' in media_dict: + thumbnail = media_dict['thumbnail'] + if isinstance(thumbnail, types.InputFile): + thumbnail_key = 'thumbnail_' + key + files[thumbnail_key] = thumbnail + media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files From 17e0aca55bcd2e554c68140bd20b3b5390c4a727 Mon Sep 17 00:00:00 2001 From: jakie Date: Wed, 18 Dec 2024 13:29:52 +0700 Subject: [PATCH 393/480] Added new example: stars payment bot This is a example how to make a payment using telegram stars. --- examples/stars_payment.py | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 examples/stars_payment.py diff --git a/examples/stars_payment.py b/examples/stars_payment.py new file mode 100644 index 000000000..e261a5e31 --- /dev/null +++ b/examples/stars_payment.py @@ -0,0 +1,64 @@ +# Import required libraries +import telebot +from telebot import types + +bot = telebot.TeleBot('TOKEN') + +# Product prices in stars +PRICES = { + '10 Stars': 10, # $1.00 - Entry level package + '50 Stars': 45, # $4.50 - Medium package with 10% discount + '100 Stars': 80, # $8.00 - Large package with 20% discount + '500 Stars': 350 # $35.00 - Bulk package with 30% discount +} + +# Handler for /start command - Then the bot will send amount stars to purchase +@bot.message_handler(commands=['start']) +def send_welcome(message): + # Create a custom keyboard with 2 buttons per row + markup = types.ReplyKeyboardMarkup(row_width=2) + # Generate buttons for each product in our PRICES dictionary + buttons = [types.KeyboardButton(product) for product in PRICES.keys()] + # Add all buttons to the markup + markup.add(*buttons) + + # Send welcome message with the custom keyboard + bot.reply_to(message, + "Welcome to Stars Payment Bot!\nPlease select amount of stars to purchase:", + reply_markup=markup) + +# Handler for when user selects a product from the keyboard +@bot.message_handler(func=lambda message: message.text in PRICES.keys()) +def handle_product_selection(message): + # Get selected product and its price + product = message.text + price = PRICES[product] + + # Create invoice with product details + prices = [types.LabeledPrice(label=product, amount=price)] + + # Send payment invoice to user + bot.send_invoice( + message.chat.id, # Chat ID to send invoice to + title=f"Purchase {product}", # Title of the invoice + description=f"Buy {product} for your account", # Description shown on invoice + provider_token='', # Payment provider token (empty for testing) + currency='XTR', # Currency code + prices=prices, # List of prices (we only have one item) + start_parameter='stars-payment', # Deep-linking parameter + invoice_payload=product # Payload to identify the product after payment + ) + +# Pre-checkout handler - Called before payment is completed +@bot.pre_checkout_query_handler(func=lambda query: True) +def process_pre_checkout_query(pre_checkout_query): + bot.answer_pre_checkout_query(pre_checkout_query.id, ok=True) + +# Handler for successful payments +@bot.message_handler(content_types=['successful_payment']) +def handle_successful_payment(message): + # Get the product that was purchased from the invoice payload + product = message.successful_payment.invoice_payload + bot.reply_to(message, + f"Payment for {product} successful!") +bot.polling() From b0afe2d2f735173db0c361dca1f827f30213118d Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 2 Jan 2025 10:58:44 +0500 Subject: [PATCH 394/480] Bot API 8.2 full support --- README.md | 2 +- telebot/__init__.py | 72 +++++++++++++++++++++++++++++++++++++-- telebot/apihelper.py | 38 +++++++++++++++++---- telebot/async_telebot.py | 72 +++++++++++++++++++++++++++++++++++++-- telebot/asyncio_helper.py | 34 ++++++++++++++---- telebot/types.py | 10 +++++- telebot/version.py | 2 +- 7 files changed, 209 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index bbc6f1698..ff1b5159f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

diff --git a/telebot/__init__.py b/telebot/__init__.py index 51eb63d4a..ae210f130 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6250,7 +6250,8 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. @@ -6262,6 +6263,9 @@ def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_p :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver + :type pay_for_upgrade: :obj:`bool` + :param text: Text that will be shown along with the gift; 0-255 characters :type text: :obj:`str` @@ -6274,7 +6278,71 @@ def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_p :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities) + return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade) + + def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: + """ + Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifyuser + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.verify_user(self.token, user_id, custom_description=custom_description) + + def verify_chat(self, chat_id: Union[int, str], custom_description: Optional[str]=None) -> bool: + """ + Verifies a chat on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifychat + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.verify_chat(self.token, chat_id, custom_description=custom_description) + + def remove_user_verification(self, user_id: int) -> bool: + """ + Removes verification from a user who is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removeuserverification + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + + return apihelper.remove_user_verification(self.token, user_id) + + def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: + """ + Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removechatverification + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.remove_chat_verification(self.token, chat_id) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 3044b226d..887f163db 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1929,7 +1929,7 @@ def get_available_gifts(token): return _make_request(token, method_url) -def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None): +def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1938,6 +1938,36 @@ def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_ent payload['text_parse_mode'] = text_parse_mode if text_entities: payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + if pay_for_upgrade is not None: + payload['pay_for_upgrade'] = pay_for_upgrade + return _make_request(token, method_url, params=payload, method='post') + + +def verify_user(token, user_id, custom_description=None): + method_url = 'verifyUser' + payload = {'user_id': user_id} + if custom_description: + payload['custom_description'] = custom_description + return _make_request(token, method_url, params=payload, method='post') + + +def verify_chat(token, chat_id, custom_description=None): + method_url = 'verifyChat' + payload = {'chat_id': chat_id} + if custom_description: + payload['custom_description'] = custom_description + return _make_request(token, method_url, params=payload, method='post') + + +def remove_user_verification(token, user_id): + method_url = 'removeUserVerification' + payload = {'user_id': user_id} + return _make_request(token, method_url, params=payload, method='post') + + +def remove_chat_verification(token, chat_id): + method_url = 'removeChatVerification' + payload = {'chat_id': chat_id} return _make_request(token, method_url, params=payload, method='post') def set_sticker_emoji_list(token, sticker, emoji_list): @@ -2271,12 +2301,6 @@ def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media - if 'thumbnail' in media_dict: - thumbnail = media_dict['thumbnail'] - if isinstance(thumbnail, types.InputFile): - thumbnail_key = 'thumbnail_' + key - files[thumbnail_key] = thumbnail - media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 0e298ace7..288b5f26e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7707,7 +7707,8 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) - async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. @@ -7719,6 +7720,9 @@ async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver + :type pay_for_upgrade: :obj:`bool` + :param text: Text that will be shown along with the gift; 0-255 characters :type text: :obj:`str` @@ -7731,7 +7735,71 @@ async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities) + return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade) + + async def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: + """ + Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifyuser + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.verify_user(self.token, user_id, custom_description) + + async def verify_chat(self, chat_id: Union[int, str], custom_description: Optional[str]=None) -> bool: + """ + Verifies a chat on behalf of the organization which is represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#verifychat + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :param custom_description: Custom description for the verification; 0-70 characters. Must be empty if the organization isn't allowed to provide a custom verification description. + :type custom_description: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + + return await asyncio_helper.verify_chat(self.token, chat_id, custom_description) + + async def remove_user_verification(self, user_id: int) -> bool: + """ + Removes verification from a user who is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removeuserverification + + :param user_id: Unique identifier of the target user + :type user_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + + """ + return await asyncio_helper.remove_user_verification(self.token, user_id) + + async def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: + """ + Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removechatverification + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` | :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.remove_chat_verification(self.token, chat_id) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index d11245d56..8c5b9ace6 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1916,7 +1916,7 @@ async def delete_sticker_set(token, name): payload = {'name': name} return await _process_request(token, method_url, params=payload, method='post') -async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None): +async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1925,6 +1925,32 @@ async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, te payload['text_parse_mode'] = text_parse_mode if text_entities: payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + if pay_for_upgrade is not None: + payload['pay_for_upgrade'] = pay_for_upgrade + return await _process_request(token, method_url, params=payload, method='post') + +async def verify_user(token, user_id, custom_description=None): + method_url = 'verifyUser' + payload = {'user_id': user_id} + if custom_description: + payload['custom_description'] = custom_description + return await _process_request(token, method_url, params=payload, method='post') + +async def verify_chat(token, chat_id, custom_description=None): + method_url = 'verifyChat' + payload = {'chat_id': chat_id} + if custom_description: + payload['custom_description'] = custom_description + return await _process_request(token, method_url, params=payload, method='post') + +async def remove_user_verification(token, user_id): + method_url = 'removeUserVerification' + payload = {'user_id': user_id} + return await _process_request(token, method_url, params=payload, method='post') + +async def remove_chat_verification(token, chat_id): + method_url = 'removeChatVerification' + payload = {'chat_id': chat_id} return await _process_request(token, method_url, params=payload, method='post') async def get_available_gifts(token): @@ -2243,12 +2269,6 @@ async def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media - if 'thumbnail' in media_dict: - thumbnail = media_dict['thumbnail'] - if isinstance(thumbnail, types.InputFile): - thumbnail_key = 'thumbnail_' + key - files[thumbnail_key] = thumbnail - media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files diff --git a/telebot/types.py b/telebot/types.py index e4dafaa7d..301ae61a1 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -4449,6 +4449,10 @@ def __init__(self, id: str, title: str, input_message_content: InputMessageConte self.thumbnail_width: Optional[int] = thumbnail_width self.thumbnail_height: Optional[int] = thumbnail_height + if hide_url: + log_deprecation_warning('The parameter "hide_url" is deprecated. Pass an empty string as url instead.') + self.url = '' + @property def thumb_url(self) -> str: @@ -11059,6 +11063,9 @@ class Gift(JsonDeserializable): :param star_count: The number of Telegram Stars that must be paid to send the sticker :type star_count: :obj:`int` + :param upgrade_star_count: Optional. The number of Telegram Stars that must be paid to upgrade the gift to a unique one + :type upgrade_star_count: :obj:`int` + :param total_count: Optional. The total number of the gifts of this type that can be sent; for limited gifts only :type total_count: :obj:`int` @@ -11069,12 +11076,13 @@ class Gift(JsonDeserializable): :rtype: :class:`Gift` """ - def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, **kwargs): + def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, upgrade_star_count=None, **kwargs): self.id: str = id self.sticker: Sticker = sticker self.star_count: int = star_count self.total_count: Optional[int] = total_count self.remaining_count: Optional[int] = remaining_count + self.upgrade_star_count: Optional[int] = upgrade_star_count @classmethod def de_json(cls, json_string): diff --git a/telebot/version.py b/telebot/version.py index 9317bd5d7..bde2003e4 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.25.0' +__version__ = '4.24.0' From ebb291af1c2495a997a7e2f8515a98cf1ed1c37c Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 3 Jan 2025 19:21:04 +0500 Subject: [PATCH 395/480] fix issues --- telebot/apihelper.py | 6 ++++++ telebot/async_telebot.py | 4 ++-- telebot/asyncio_helper.py | 6 ++++++ telebot/version.py | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 887f163db..69f3f8e4f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2301,6 +2301,12 @@ def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media + if 'thumbnail' in media_dict: + thumbnail = media_dict['thumbnail'] + if isinstance(thumbnail, types.InputFile): + thumbnail_key = 'thumbnail_' + key + files[thumbnail_key] = thumbnail + media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 288b5f26e..a3f717dff 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7752,7 +7752,7 @@ async def verify_user(self, user_id: int, custom_description: Optional[str]=None :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.verify_user(self.token, user_id, custom_description) + return await asyncio_helper.verify_user(self.token, user_id, custom_description=custom_description) async def verify_chat(self, chat_id: Union[int, str], custom_description: Optional[str]=None) -> bool: """ @@ -7770,7 +7770,7 @@ async def verify_chat(self, chat_id: Union[int, str], custom_description: Option :rtype: :obj:`bool` """ - return await asyncio_helper.verify_chat(self.token, chat_id, custom_description) + return await asyncio_helper.verify_chat(self.token, chat_id, custom_description=custom_description) async def remove_user_verification(self, user_id: int) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 8c5b9ace6..ba51a7daa 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2269,6 +2269,12 @@ async def convert_input_media_array(array): if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media + if 'thumbnail' in media_dict: + thumbnail = media_dict['thumbnail'] + if isinstance(thumbnail, types.InputFile): + thumbnail_key = 'thumbnail_' + key + files[thumbnail_key] = thumbnail + media_dict['thumbnail'] = 'attach://' + thumbnail_key media.append(media_dict) return json.dumps(media), files diff --git a/telebot/version.py b/telebot/version.py index bde2003e4..9317bd5d7 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.24.0' +__version__ = '4.25.0' From ab7de46fdadacddb04dc1c36b9ab317f7bab7b0d Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 5 Jan 2025 00:28:05 +0300 Subject: [PATCH 396/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index fb559d15e..0ce35e8db 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.25.0' +release = '4.26.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index ebb66f1c4..471aaa45b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.25.0" +version = "4.26.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index 9317bd5d7..b37f3e662 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.25.0' +__version__ = '4.26.0' From 198d92f8b3c1d5b075ab4aa83ed3624583e210b7 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 10 Feb 2025 20:43:30 +0400 Subject: [PATCH 397/480] Fix deprecation bug #2451 --- telebot/asyncio_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index ba51a7daa..e076b8e26 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -37,7 +37,7 @@ def __init__(self) -> None: async def create_session(self): self.session = aiohttp.ClientSession(connector=aiohttp.TCPConnector( limit=REQUEST_LIMIT, - ssl_context=self.ssl_context + ssl=self.ssl_context )) return self.session From 36b2753a1b5c12851d42a5e5c869a0b40949c2a3 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:06:45 +0400 Subject: [PATCH 398/480] added chat_id to send_gift, user_id made optional; --- telebot/__init__.py | 19 +++++++++++++------ telebot/apihelper.py | 7 ++++++- telebot/async_telebot.py | 21 +++++++++++++++------ telebot/asyncio_helper.py | 7 ++++++- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index ae210f130..eadd5aae8 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6250,19 +6250,23 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + def send_gift(self, gift_id: str, user_id: Optional[Union[str, int]] = None, chat_id: Optional[Union[str, int]] = None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#sendgift - :param user_id: Unique identifier of the target user that will receive the gift - :type user_id: :obj:`int` - :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param user_id: Required if chat_id is not specified. Unique identifier of the target user who will receive the gift. + :type user_id::obj:`int` | :obj:`str` + + :param chat_id: Required if user_id is not specified. Unique identifier for the chat or username of the channel + (in the format @channelusername) that will receive the gift. + :type chat_id: :obj:`int` | :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver :type pay_for_upgrade: :obj:`bool` @@ -6278,8 +6282,11 @@ def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_p :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.send_gift(self.token, user_id, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, - pay_for_upgrade=pay_for_upgrade) + if user_id is None and chat_id is None: + raise ValueError("Either user_id or chat_id must be specified.") + + return apihelper.send_gift(self.token, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, + pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 69f3f8e4f..899470031 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1929,7 +1929,8 @@ def get_available_gifts(token): return _make_request(token, method_url) -def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): +def send_gift(token, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None, + chat_id=None, user_id=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1940,6 +1941,10 @@ def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_ent payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) if pay_for_upgrade is not None: payload['pay_for_upgrade'] = pay_for_upgrade + if chat_id: + payload['chat_id'] = chat_id + if user_id: + payload['user_id'] = user_id return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index a3f717dff..7d2008077 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7707,19 +7707,24 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) - async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, text_parse_mode: Optional[str]=None, - text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: + async def send_gift(self, gift_id: str, user_id: Optional[Union[str, int]] = None, chat_id: Optional[Union[str, int]] = None, + text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None, + pay_for_upgrade: Optional[bool]=None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#sendgift - :param user_id: Unique identifier of the target user that will receive the gift - :type user_id: :obj:`int` - :param gift_id: Identifier of the gift :type gift_id: :obj:`str` + :param user_id: Required if chat_id is not specified. Unique identifier of the target user who will receive the gift. + :type user_id::obj:`int` | :obj:`str` + + :param chat_id: Required if user_id is not specified. Unique identifier for the chat or username of the channel + (in the format @channelusername) that will receive the gift. + :type chat_id: :obj:`int` | :obj:`str` + :param pay_for_upgrade: Pass True to pay for the gift upgrade from the bot's balance, thereby making the upgrade free for the receiver :type pay_for_upgrade: :obj:`bool` @@ -7735,7 +7740,11 @@ async def send_gift(self, user_id: int, gift_id: str, text: Optional[str]=None, :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.send_gift(self.token, user_id, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade) + if user_id is None and chat_id is None: + raise ValueError("Either user_id or chat_id must be specified.") + + return await asyncio_helper.send_gift(self.token, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade, + chat_id=chat_id, user_id=user_id) async def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index e076b8e26..f0ca629c8 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1916,7 +1916,8 @@ async def delete_sticker_set(token, name): payload = {'name': name} return await _process_request(token, method_url, params=payload, method='post') -async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None): +async def send_gift(token, gift_id, text=None, text_parse_mode=None, text_entities=None, pay_for_upgrade=None, + user_id=None, chat_id=None): method_url = 'sendGift' payload = {'user_id': user_id, 'gift_id': gift_id} if text: @@ -1927,6 +1928,10 @@ async def send_gift(token, user_id, gift_id, text=None, text_parse_mode=None, te payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) if pay_for_upgrade is not None: payload['pay_for_upgrade'] = pay_for_upgrade + if chat_id: + payload['chat_id'] = chat_id + if user_id: + payload['user_id'] = user_id return await _process_request(token, method_url, params=payload, method='post') async def verify_user(token, user_id, custom_description=None): From d7c2a326fa50b5d503a5b965214a093ce70c4640 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:08:39 +0400 Subject: [PATCH 399/480] Added can_send_gift to ChatFullInfo --- telebot/types.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 301ae61a1..dd0824f9f 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -688,6 +688,13 @@ class ChatFullInfo(JsonDeserializable): :param permissions: Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. :type permissions: :class:`telebot.types.ChatPermissions` + :param can_send_gift: Optional. True, if gifts can be sent to the chat + :type can_send_gift: :obj:`bool` + + :param can_send_paid_media: Optional. True, if paid media messages can be sent or forwarded to the channel chat. + The field is available only for channel chats. + :type can_send_paid_media: :obj:`bool` + :param slow_mode_delay: Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unpriviledged user; in seconds. Returned only in getChat. :type slow_mode_delay: :obj:`int` @@ -728,10 +735,6 @@ class ChatFullInfo(JsonDeserializable): :param location: Optional. For supergroups, the location to which the supergroup is connected. Returned only in getChat. :type location: :class:`telebot.types.ChatLocation` - :param can_send_paid_media: Optional. True, if paid media messages can be sent or forwarded to the channel chat. - The field is available only for channel chats. - :type can_send_paid_media: :obj:`bool` - :return: Instance of the class :rtype: :class:`telebot.types.ChatFullInfo` """ @@ -774,7 +777,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, business_opening_hours=None, personal_chat=None, birthdate=None, - can_send_paid_media=None, **kwargs): + can_send_paid_media=None, can_send_gift=None, **kwargs): self.id: int = id self.type: str = type self.title: Optional[str] = title @@ -819,6 +822,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.personal_chat: Optional[Chat] = personal_chat self.birthdate: Optional[Birthdate] = birthdate self.can_send_paid_media: Optional[bool] = can_send_paid_media + self.can_send_gift: Optional[bool] = can_send_gift class Chat(ChatFullInfo): From eb2cfd221d2b728200e9682d637f20298a10a683 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:10:31 +0400 Subject: [PATCH 400/480] Added TransactionPartnerChat --- telebot/types.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index dd0824f9f..5bdf918bf 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10423,6 +10423,8 @@ def de_json(cls, json_string): return TransactionPartnerAffiliateProgram.de_json(obj) elif obj["type"] == "other": return TransactionPartnerOther.de_json(obj) + elif obj["type"] == "chat": + return TransactionPartnerChat.de_json(obj) # noinspection PyShadowingBuiltins @@ -11196,3 +11198,36 @@ def de_json(cls, json_string): return cls(**obj) +class TransactionPartnerChat(TransactionPartner): + """ + Describes a transaction with a chat. + + Telegram documentation: https://core.telegram.org/bots/api#transactionpartnerchat + + :param type: Type of the transaction partner, always “chat” + :type type: :obj:`str` + + :param chat: Information about the chat + :type chat: :class:`Chat` + + :param gift: Optional. The gift sent to the chat by the bot + :type gift: :class:`Gift` + + :return: Instance of the class + :rtype: :class:`TransactionPartnerChat` + """ + + def __init__(self, type, chat, gift=None, **kwargs): + self.type: str = type + self.chat: Chat = chat + self.gift: Optional[Gift] = gift + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['chat'] = Chat.de_json(obj['chat']) + if 'gift' in obj: + obj['gift'] = Gift.de_json(obj['gift']) + return cls(**obj) + From 73f34d316ce3fab33120ccefd3524d2f3956595b Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:12:51 +0400 Subject: [PATCH 401/480] Added the fields cover and start_timestamp to the class Video, containing a message-specific cover and a start timestamp for the video. --- telebot/types.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 5bdf918bf..3ecfd0905 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1985,6 +1985,12 @@ class Video(JsonDeserializable): :param thumbnail: Optional. Video thumbnail :type thumbnail: :class:`telebot.types.PhotoSize` + :param cover: Optional. Available sizes of the cover of the video in the message + :type cover: List[:class:`telebot.types.PhotoSize`] + + :param start_timestamp: Optional. Timestamp in seconds from which the video will play in the message + :type start_timestamp: :obj:`int` + :param file_name: Optional. Original filename as defined by sender :type file_name: :obj:`str` @@ -2005,9 +2011,12 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'thumbnail' in obj and 'file_id' in obj['thumbnail']: obj['thumbnail'] = PhotoSize.de_json(obj['thumbnail']) + if 'cover' in obj: + obj['cover'] = [PhotoSize.de_json(c) for c in obj['cover']] return cls(**obj) - def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=None, file_name=None, mime_type=None, file_size=None, **kwargs): + def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=None, file_name=None, mime_type=None, file_size=None, + cover=None, start_timestamp=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id self.width: int = width @@ -2017,6 +2026,8 @@ def __init__(self, file_id, file_unique_id, width, height, duration, thumbnail=N self.file_name: Optional[str] = file_name self.mime_type: Optional[str] = mime_type self.file_size: Optional[int] = file_size + self.cover: Optional[List[PhotoSize]] = cover + self.start_timestamp: Optional[int] = start_timestamp @property def thumb(self) -> Optional[PhotoSize]: From fcee398fe0f4e16e6c895b7f7657ba9f1e8cd81f Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:20:15 +0400 Subject: [PATCH 402/480] Added the parameters cover and start_timestamp to the method sendVideo, allowing bots to specify a cover and a start timestamp for the videos they send. --- telebot/__init__.py | 19 ++++++++++++++++--- telebot/apihelper.py | 13 ++++++++++++- telebot/async_telebot.py | 14 ++++++++++++-- telebot/asyncio_helper.py | 12 +++++++++++- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index eadd5aae8..3629f23a6 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2824,7 +2824,9 @@ def send_video( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + cover: Optional[Union[Any, str]]=None, + start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -2845,8 +2847,18 @@ def send_video( :param height: Video height :type height: :obj:`int` - :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . + :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. + A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, + so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` + + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -2949,7 +2961,8 @@ def send_video( thumbnail=thumbnail, height=height, width=width, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + cover=cover, start_timestamp=start_timestamp) ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 899470031..9f7325a08 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -783,7 +783,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, + cover=None, start_timestamp=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -835,6 +836,16 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if cover: + if not util.is_string(cover): + if files: + files['cover'] = cover + else: + files = {'cover': cover} + else: + payload['cover'] = cover + if start_timestamp: + payload['start_timestamp'] = start_timestamp return _make_request(token, method_url, params=payload, files=files, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 7d2008077..2022d37c4 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -4341,7 +4341,9 @@ async def send_video( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + cover: Optional[Union[Any, str]]=None, + start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4364,6 +4366,14 @@ async def send_video( :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` + + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -4467,7 +4477,7 @@ async def send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, cover=cover, start_timestamp=start_timestamp)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index f0ca629c8..360138bd8 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -789,7 +789,7 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, cover=None, start_timestamp=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -841,6 +841,16 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if cover: + if not util.is_string(cover): + if files: + files['cover'] = cover + else: + files = {'cover': cover} + else: + payload['cover'] = cover + if start_timestamp: + payload['start_timestamp'] = start_timestamp return await _process_request(token, method_url, params=payload, files=files, method='post') From 1ccc96669a8e74770eb421a161280a06345a26c6 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:24:28 +0400 Subject: [PATCH 403/480] Added the fields cover and start_timestamp to the classes InputMediaVideo and InputPaidMediaVideo, allowing bots to edit video cover and start timestamp and specify them for videos in albums and paid media. --- telebot/types.py | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 3ecfd0905..af0d4cf74 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6802,6 +6802,14 @@ class InputMediaVideo(InputMedia): multipart/form-data under . More information on Sending Files » :type thumbnail: InputFile or :obj:`str` + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` + :param caption: Optional. Caption of the video to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -6839,7 +6847,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, caption_entities: Optional[List[MessageEntity]] = None, width: Optional[int] = None, height: Optional[int] = None, duration: Optional[int] = None, supports_streaming: Optional[bool] = None, has_spoiler: Optional[bool] = None, - show_caption_above_media: Optional[bool] = None): + show_caption_above_media: Optional[bool] = None, cover: Optional[Union[str, InputFile]] = None, + start_timestamp: Optional[int] = None): super(InputMediaVideo, self).__init__( type="video", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) self.thumbnail: Optional[Union[str, InputFile]] = thumbnail @@ -6849,6 +6858,8 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, self.supports_streaming: Optional[bool] = supports_streaming self.has_spoiler: Optional[bool] = has_spoiler self.show_caption_above_media: Optional[bool] = show_caption_above_media + self.cover: Optional[str] = cover + self.start_timestamp: Optional[int] = start_timestamp @property def thumb(self) -> Optional[Union[str, Any]]: @@ -6871,6 +6882,10 @@ def to_dict(self): ret['has_spoiler'] = self.has_spoiler if self.show_caption_above_media is not None: ret['show_caption_above_media'] = self.show_caption_above_media + if self.cover: + ret['cover'] = self.cover + if self.start_timestamp: + ret['start_timestamp'] = self.start_timestamp return ret @@ -10899,6 +10914,14 @@ class InputPaidMediaVideo(InputPaidMedia): More information on Sending Files » :type thumbnail: :class:`InputFile` + :param cover: Cover for the video in the message. Pass a file_id to send a file that exists on the Telegram servers (recommended), + pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under + name. More information on Sending Files » + :type cover: :obj:`str` or :class:`telebot.types.InputFile` + + :param start_timestamp: Start timestamp for the video in the message + :type start_timestamp: :obj:`int` + :param width: Optional. Video width :type width: :obj:`int` @@ -10917,13 +10940,16 @@ class InputPaidMediaVideo(InputPaidMedia): """ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[InputFile] = None, width: Optional[int] = None, height: Optional[int] = None, duration: Optional[int] = None, supports_streaming: Optional[bool] = None, - **kwargs): + cover: Optional[Union[str,InputFile]] = None, start_timestamp: Optional[int] = None, **kwargs): super().__init__(type='video', media=media) self.thumbnail: Optional[Union[str,InputFile]] = thumbnail self.width: Optional[int] = width self.height: Optional[int] = height self.duration: Optional[int] = duration self.supports_streaming: Optional[bool] = supports_streaming + self.cover: Optional[Union[str,InputFile]] = cover + self.start_timestamp: Optional[int] = start_timestamp + def to_dict(self): @@ -10938,6 +10964,10 @@ def to_dict(self): data['duration'] = self.duration if self.supports_streaming is not None: data['supports_streaming'] = self.supports_streaming + if self.cover: + data['cover'] = self.cover + if self.start_timestamp: + data['start_timestamp'] = self.start_timestamp return data class RefundedPayment(JsonDeserializable): From 56d14dca89e7d72a8ecddda33a1363867558c50a Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:31:05 +0400 Subject: [PATCH 404/480] Added the parameter video_start_timestamp to the methods forwardMessage and copyMessage, allowing bots to change the start timestamp for forwarded and copied videos. --- telebot/__init__.py | 18 ++++++++++++++---- telebot/apihelper.py | 10 ++++++++-- telebot/async_telebot.py | 28 ++++++++++++++++++++-------- telebot/asyncio_helper.py | 8 ++++++-- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 3629f23a6..015997631 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1810,7 +1810,8 @@ def forward_message( message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + video_start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -1825,6 +1826,9 @@ def forward_message( :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) :type from_chat_id: :obj:`int` or :obj:`str` + :param video_start_timestamp: New start timestamp for the forwarded video in the message + :type video_start_timestamp: :obj:`int` + :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` @@ -1846,7 +1850,8 @@ def forward_message( return types.Message.de_json( apihelper.forward_message( self.token, chat_id, from_chat_id, message_id, disable_notification=disable_notification, - timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id)) + timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, + video_start_timestamp=video_start_timestamp)) def copy_message( @@ -1865,7 +1870,8 @@ def copy_message( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.MessageID: + allow_paid_broadcast: Optional[bool]=None, + video_start_timestamp: Optional[int]=None) -> types.MessageID: """ Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. @@ -1883,6 +1889,9 @@ def copy_message( :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` + :param video_start_timestamp: New start timestamp for the copied video in the message + :type video_start_timestamp: :obj:`int` + :param caption: New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept :type caption: :obj:`str` @@ -1956,7 +1965,8 @@ def copy_message( parse_mode=parse_mode, caption_entities=caption_entities, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + video_start_timestamp=video_start_timestamp)) def delete_message(self, chat_id: Union[int, str], message_id: int, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 9f7325a08..879dfdec5 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -424,7 +424,8 @@ def get_chat_member(token, chat_id, user_id): def forward_message( token, chat_id, from_chat_id, message_id, - disable_notification=None, timeout=None, protect_content=None, message_thread_id=None): + disable_notification=None, timeout=None, protect_content=None, message_thread_id=None, + video_start_timestamp=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -435,12 +436,15 @@ def forward_message( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return _make_request(token, method_url, params=payload) def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, - reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None): + reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None, + video_start_timestamp=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -465,6 +469,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return _make_request(token, method_url, params=payload) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 2022d37c4..3d9860054 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3337,7 +3337,8 @@ async def forward_message( message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, - message_thread_id: Optional[int]=None) -> types.Message: + message_thread_id: Optional[int]=None, + video_start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -3355,6 +3356,9 @@ async def forward_message( :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` + :param video_start_timestamp: New start timestamp for the forwarded video in the message + :type video_start_timestamp: :obj:`int` + :param protect_content: Protects the contents of the forwarded message from forwarding and saving :type protect_content: :obj:`bool` @@ -3371,8 +3375,9 @@ async def forward_message( protect_content = self.protect_content if (protect_content is None) else protect_content return types.Message.de_json( - await asyncio_helper.forward_message(self.token, chat_id, from_chat_id, message_id, disable_notification, timeout, protect_content, - message_thread_id)) + await asyncio_helper.forward_message(self.token, chat_id=chat_id, from_chat_id=from_chat_id, message_id=message_id, + disable_notification=disable_notification, protect_content=protect_content, + timeout=timeout, message_thread_id=message_thread_id, video_start_timestamp=video_start_timestamp)) async def copy_message( self, chat_id: Union[int, str], @@ -3390,7 +3395,8 @@ async def copy_message( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.MessageID: + allow_paid_broadcast: Optional[bool]=None, + video_start_timestamp: Optional[bool]=None) -> types.MessageID: """ Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, @@ -3405,9 +3411,13 @@ async def copy_message( :param from_chat_id: Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) :type from_chat_id: :obj:`int` or :obj:`str` + :param message_id: Message identifier in the chat specified in from_chat_id :type message_id: :obj:`int` + :param video_start_timestamp: New start timestamp for the forwarded video in the message + :type video_start_timestamp: :obj:`int` + :param caption: New caption for media, 0-1024 characters after entities parsing. If not specified, the original caption is kept :type caption: :obj:`str` @@ -3478,10 +3488,12 @@ async def copy_message( reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply return types.MessageID.de_json( - await asyncio_helper.copy_message(self.token, chat_id, from_chat_id, message_id, caption, parse_mode, caption_entities, - disable_notification, reply_markup, - timeout, protect_content, message_thread_id, reply_parameters, show_caption_above_media=show_caption_above_media, - allow_paid_broadcast=allow_paid_broadcast)) + await asyncio_helper.copy_message(self.token, chat_id=chat_id, from_chat_id=from_chat_id, message_id=message_id, + caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, + disable_notification=disable_notification, protect_content=protect_content, + reply_parameters=reply_parameters, reply_markup=reply_markup, timeout=timeout, + message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, + allow_paid_broadcast=allow_paid_broadcast, video_start_timestamp=video_start_timestamp)) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 360138bd8..99937ff63 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -429,7 +429,7 @@ async def get_chat_member(token, chat_id, user_id): async def forward_message( token, chat_id, from_chat_id, message_id, disable_notification=None, timeout=None, protect_content=None, - message_thread_id=None): + message_thread_id=None, video_start_timestamp=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -440,13 +440,15 @@ async def forward_message( payload['protect_content'] = protect_content if message_thread_id: payload['message_thread_id'] = message_thread_id + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return await _process_request(token, method_url, params=payload) async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, video_start_timestamp=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -471,6 +473,8 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if video_start_timestamp: + payload['video_start_timestamp'] = video_start_timestamp return await _process_request(token, method_url, params=payload) From d5c28da62506a033b5ee72685b47a1067e72a8e2 Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 13 Feb 2025 18:31:52 +0400 Subject: [PATCH 405/480] Update Bot API Version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff1b5159f..7431dc001 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From 7d82d8f835e1bf05831b97378274fbbc644a543d Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 15 Feb 2025 16:27:47 +0400 Subject: [PATCH 406/480] Ensure backward compatibility for send_gift --- telebot/__init__.py | 8 ++++++-- telebot/async_telebot.py | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 015997631..2ac86cf06 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6273,8 +6273,9 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, gift_id: str, user_id: Optional[Union[str, int]] = None, chat_id: Optional[Union[str, int]] = None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, - text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None) -> bool: + def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None, + chat_id: Optional[Union[str, int]] = None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. @@ -6308,6 +6309,9 @@ def send_gift(self, gift_id: str, user_id: Optional[Union[str, int]] = None, cha if user_id is None and chat_id is None: raise ValueError("Either user_id or chat_id must be specified.") + if gift_id is None: + raise ValueError("gift_id must be specified.") + return apihelper.send_gift(self.token, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 3d9860054..bc251220a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7729,9 +7729,9 @@ async def delete_sticker_set(self, name:str) -> bool: return await asyncio_helper.delete_sticker_set(self.token, name) - async def send_gift(self, gift_id: str, user_id: Optional[Union[str, int]] = None, chat_id: Optional[Union[str, int]] = None, + async def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None, - pay_for_upgrade: Optional[bool]=None) -> bool: + pay_for_upgrade: Optional[bool]=None, chat_id: Optional[Union[str, int]] = None) -> bool: """ Sends a gift to the given user. The gift can't be converted to Telegram Stars by the user. Returns True on success. @@ -7765,6 +7765,9 @@ async def send_gift(self, gift_id: str, user_id: Optional[Union[str, int]] = Non if user_id is None and chat_id is None: raise ValueError("Either user_id or chat_id must be specified.") + if gift_id is None: + raise ValueError("gift_id must be specified.") + return await asyncio_helper.send_gift(self.token, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) From fb0e9b32fec3898a9bac50daaba9bdb9f6426ce8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Mar 2025 03:21:16 +0000 Subject: [PATCH 407/480] Bump gunicorn in /examples/serverless/flask_google_cloud_bot Bumps [gunicorn](https://github.com/benoitc/gunicorn) from 22.0.0 to 23.0.0. - [Release notes](https://github.com/benoitc/gunicorn/releases) - [Commits](https://github.com/benoitc/gunicorn/compare/22.0.0...23.0.0) --- updated-dependencies: - dependency-name: gunicorn dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- examples/serverless/flask_google_cloud_bot/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/serverless/flask_google_cloud_bot/requirements.txt b/examples/serverless/flask_google_cloud_bot/requirements.txt index e08389a50..a9c951e71 100644 --- a/examples/serverless/flask_google_cloud_bot/requirements.txt +++ b/examples/serverless/flask_google_cloud_bot/requirements.txt @@ -1,4 +1,4 @@ pyTelegramBotAPI==4.11.0 Flask==3.0.0 -gunicorn==22.0.0 +gunicorn==23.0.0 Werkzeug==3.0.6 From 19bf13815582140e25ca7ff540c839e282fc41db Mon Sep 17 00:00:00 2001 From: pplulee Date: Sat, 5 Apr 2025 23:22:22 +0800 Subject: [PATCH 408/480] Add support for processing language parameter in message entities --- telebot/formatting.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index 801a67ec1..aa24c2007 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -418,13 +418,16 @@ def apply_html_entities(text: str, entities: Optional[List], custom_subs: Option utf16_text = text.encode("utf-16-le") html_text = "" - def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): + def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None, language=None): upd_text = upd_text.decode("utf-16-le") if subst_type == "text_mention": subst_type = "text_link" url = "tg://user?id={0}".format(user.id) elif subst_type == "mention": url = "https://t.me/{0}".format(upd_text[1:]) + elif subst_type == "pre": + if language is not None: + return '
{1}
'.format(language, upd_text) upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") if not subst_type or not _subs.get(subst_type): return upd_text @@ -444,14 +447,16 @@ def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): offset = entity.offset new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, - url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id, + language=entity.language) start_index = len(html_text) html_text += new_string offset += entity.length end_index = len(html_text) elif entity.offset == offset: new_string = func(utf16_text[offset * 2: (offset + entity.length) * 2], subst_type=entity.type, - url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id) + url=entity.url, user=entity.user, custom_emoji_id=entity.custom_emoji_id, + language=entity.language) start_index = len(html_text) html_text += new_string end_index = len(html_text) @@ -463,7 +468,8 @@ def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None): # And we don't change it). entity_string = html_text[start_index: end_index].encode("utf-16-le") formatted_string = func(entity_string, subst_type=entity.type, url=entity.url, user=entity.user, - custom_emoji_id=entity.custom_emoji_id). \ + custom_emoji_id=entity.custom_emoji_id, + language=entity.language). \ replace("&", "&").replace("<", "<").replace(">", ">") html_text = html_text[:start_index] + formatted_string + html_text[end_index:] end_index = len(html_text) From e270371d0277af3a1b197826bc5a07f3035bd42e Mon Sep 17 00:00:00 2001 From: pplulee Date: Sun, 6 Apr 2025 12:11:06 +0800 Subject: [PATCH 409/480] Add test for HTML parsing --- tests/test_telebot.py | 80 +++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 8b04ac402..4c364d952 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -44,11 +44,11 @@ def test_message_listener(self): def listener(messages): assert len(messages) == 100 - tb = telebot.TeleBot('') + tb = telebot.TeleBot(TOKEN) tb.set_update_listener(listener) def test_message_handler(self): - tb = telebot.TeleBot('') + tb = telebot.TeleBot(TOKEN) msg = self.create_text_message('/help') @tb.message_handler(commands=['help', 'start']) @@ -60,7 +60,7 @@ def command_handler(message): assert msg.text == 'got' def test_message_handler_reg(self): - bot = telebot.TeleBot('') + bot = telebot.TeleBot(TOKEN) msg = self.create_text_message(r'https://web.telegram.org/') # noinspection PyUnusedLocal @@ -73,7 +73,7 @@ def command_url(message): assert msg.text == 'got' def test_message_handler_lambda(self): - bot = telebot.TeleBot('') + bot = telebot.TeleBot(TOKEN) msg = self.create_text_message(r'lambda_text') # noinspection PyUnusedLocal @@ -86,7 +86,7 @@ def command_url(message): assert msg.text == 'got' def test_message_handler_lambda_fail(self): - bot = telebot.TeleBot('') + bot = telebot.TeleBot(TOKEN) msg = self.create_text_message(r'text') # noinspection PyUnusedLocal @@ -99,7 +99,7 @@ def command_url(message): assert not msg.text == 'got' def test_message_handler_reg_fail(self): - bot = telebot.TeleBot('') + bot = telebot.TeleBot(TOKEN) msg = self.create_text_message(r'web.telegram.org/') # noinspection PyUnusedLocal @@ -147,6 +147,7 @@ def test_send_file_with_filename(self): ret_msg = tb.send_document(CHAT_ID, file_data) assert ret_msg.message_id + file_data.seek(0) ret_msg = tb.send_document(CHAT_ID, file_data, visible_file_name="test.jpg") assert ret_msg.message_id @@ -529,28 +530,31 @@ def create_message_update(text): params = {'text': text} chat = types.User(11, False, 'test') message = types.Message(1, None, None, chat, 'text', params, "") - edited_message = None - channel_post = None - edited_channel_post = None - inline_query = None - chosen_inline_result = None - callback_query = None - shipping_query = None - pre_checkout_query = None - poll = None - poll_answer = None - my_chat_member = None - chat_member = None - chat_join_request = None - message_reaction = None - message_reaction_count = None - chat_boost = None - chat_boost_removed = None - purchased_paid_media = None - return types.Update(-1001234038283, message, edited_message, channel_post, edited_channel_post, inline_query, - chosen_inline_result, callback_query, shipping_query, pre_checkout_query, poll, poll_answer, - my_chat_member, chat_member, chat_join_request, message_reaction, message_reaction_count, chat_boost, chat_boost_removed, - purchased_paid_media) + return types.Update( + update_id=-1001234038283, + message=message, + edited_message=None, + channel_post=None, + edited_channel_post=None, + inline_query=None, + chosen_inline_result=None, + callback_query=None, + shipping_query=None, + pre_checkout_query=None, + poll=None, + poll_answer=None, + my_chat_member=None, + chat_member=None, + chat_join_request=None, + message_reaction=None, + message_reaction_count=None, + chat_boost=None, + removed_chat_boost=None, + purchased_paid_media=None, + business_message=None, + business_connection=None, + edited_business_message=None, + deleted_business_messages=None, ) def test_is_string_unicode(self): s1 = u'string' @@ -657,7 +661,7 @@ def test_typed_middleware_handler(self): apihelper.ENABLE_MIDDLEWARE = True - tb = telebot.TeleBot('') + tb = telebot.TeleBot(TOKEN) update = self.create_message_update('/help') # noinspection PyUnusedLocal @@ -678,7 +682,7 @@ def test_default_middleware_handler(self): apihelper.ENABLE_MIDDLEWARE = True - tb = telebot.TeleBot('') + tb = telebot.TeleBot(TOKEN) update = self.create_message_update('/help') # noinspection PyUnusedLocal @@ -703,3 +707,19 @@ def test_chat_permissions(self): #tb = telebot.TeleBot(TOKEN) #permissions = types.ChatPermissions(can_send_messages=True, can_send_polls=False) #msg = tb.set_chat_permissions(CHAT_ID, permissions) + + def test_apply_html_entities(self): + text = { + "*bold*": "bold", + "__italic__": "italic", + "~strikethrough~": "strikethrough", + "`inline code`": "inline code", + "```\ncode block```": "
code block
", + "```python\nprint('Hello, world!')\n```": "
print('Hello, world!')
", + "[link](http://example.com/)": "link", + ">blockquote": "
blockquote
", + } + tb = telebot.TeleBot(TOKEN) + for key, value in text.items(): + ret_msg = tb.send_message(CHAT_ID, text=key, parse_mode='MarkdownV2') + assert telebot.formatting.apply_html_entities(ret_msg.text, ret_msg.entities, None) == value From d25dae870fc88bad9ff9e62a90587b07bed45eb0 Mon Sep 17 00:00:00 2001 From: pplulee Date: Sun, 6 Apr 2025 22:03:01 +0800 Subject: [PATCH 410/480] Fix special character conversion --- telebot/formatting.py | 5 ++--- tests/test_telebot.py | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/formatting.py b/telebot/formatting.py index aa24c2007..0e300f7c1 100644 --- a/telebot/formatting.py +++ b/telebot/formatting.py @@ -425,15 +425,14 @@ def func(upd_text, subst_type=None, url=None, user=None, custom_emoji_id=None, l url = "tg://user?id={0}".format(user.id) elif subst_type == "mention": url = "https://t.me/{0}".format(upd_text[1:]) - elif subst_type == "pre": - if language is not None: - return '
{1}
'.format(language, upd_text) upd_text = upd_text.replace("&", "&").replace("<", "<").replace(">", ">") if not subst_type or not _subs.get(subst_type): return upd_text subs = _subs.get(subst_type) if subst_type == "custom_emoji": return subs.format(text=upd_text, custom_emoji_id=custom_emoji_id) + elif (subst_type == "pre") and language: + return "
{1}
".format(language, upd_text) return subs.format(text=upd_text, url=url) offset = 0 diff --git a/tests/test_telebot.py b/tests/test_telebot.py index 4c364d952..f395ff9c5 100644 --- a/tests/test_telebot.py +++ b/tests/test_telebot.py @@ -716,6 +716,7 @@ def test_apply_html_entities(self): "`inline code`": "inline code", "```\ncode block```": "
code block
", "```python\nprint('Hello, world!')\n```": "
print('Hello, world!')
", + "```python\nprint(1 < 2)\n```": "
print(1 < 2)
", "[link](http://example.com/)": "link", ">blockquote": "
blockquote
", } From 231d0d1294777442ff6130b38d24810a1d2d0b89 Mon Sep 17 00:00:00 2001 From: Timur Valiev Date: Wed, 9 Apr 2025 11:27:10 +0300 Subject: [PATCH 411/480] Issues 2458: missing `in` --- telebot/asyncio_filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/asyncio_filters.py b/telebot/asyncio_filters.py index 77c0559a6..83aefefe3 100644 --- a/telebot/asyncio_filters.py +++ b/telebot/asyncio_filters.py @@ -372,7 +372,7 @@ async def check(self, message): """ if isinstance(message, types.CallbackQuery): result = await self._bot.get_chat_member(message.message.chat.id, message.from_user.id) - return result.status ('creator', 'administrator') + return result.status in ('creator', 'administrator') result = await self._bot.get_chat_member(message.chat.id, message.from_user.id) return result.status in ['creator', 'administrator'] From 350bc556da35d63c4620c315f19b4dbf0cd5c918 Mon Sep 17 00:00:00 2001 From: pplulee Date: Fri, 11 Apr 2025 22:40:24 +0900 Subject: [PATCH 412/480] Add BetterForward to bots list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7431dc001..a23b5c330 100644 --- a/README.md +++ b/README.md @@ -891,5 +891,6 @@ Here are some examples of template: * [4K YouTube Downloader](https://github.com/hansanaD/TelegramYTDLBot/) - Youtube Downloader with upto 4K resolution support. * [DrinkGenius-Bot](https://t.me/cocktail_recommendation_bot) ([source](https://github.com/Povladarchik/DrinkGenius-Bot)) by [Povladarchik](https://github.com/Povladarchik). Your personal assistant in the world of cocktails. * [Pytgpt-Bot](https://t.me/pytgpt_bot) ([source](https://github.com/Simatwa/pytgpt-bot)) by [Smartwa](https://github.com/Simatwa). AI powered bot for chatting, text-to-image and text-to-speech conversions. +* [BetterForward](https://github.com/SideCloudGroup/BetterForward) by [SideCloud](https://github.com/SideCloudGroup). Probably the most reliable Message Forwarding Bot in Telegram via the Topic feature. **Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.** From c448bba171f3e09a4e5901eba5b130fb360ebc94 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 12:18:38 +0400 Subject: [PATCH 413/480] Update types.py --- telebot/types.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index af0d4cf74..6b561505c 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -9736,9 +9736,12 @@ class BusinessConnection(JsonDeserializable): :param date: Date the connection was established in Unix time :type date: :obj:`int` - :param can_reply: True, if the bot can act on behalf of the business account in chats that were active in the last 24 hours + :param can_reply: Deprecated, use :attr:`can_reply` instead. True, if the bot can reply to messages from the business account :type can_reply: :obj:`bool` + :param rights: Optional. Rights of the business bot + :type rights: :class:`BusinessBotRights` + :param is_enabled: True, if the connection is active :type is_enabled: :obj:`bool` @@ -9753,12 +9756,15 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj['user']) return cls(**obj) - def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, **kwargs): + def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, + rights=None, **kwargs): self.id: str = id self.user: User = user self.user_chat_id: int = user_chat_id self.date: int = date - self.can_reply: bool = can_reply + self.rights: Optional[BusinessBotRights] = rights + # Deprecated, use self.rights instead + self.can_reply: Optional[bool] = can_reply self.is_enabled: bool = is_enabled @@ -11272,3 +11278,80 @@ def de_json(cls, json_string): obj['gift'] = Gift.de_json(obj['gift']) return cls(**obj) + +class BusinessBotRights(JsonDeserializable): + """ + Represents the rights of a business bot. + + Telegram documentation: https://core.telegram.org/bots/api#businessbotrights + + :param can_reply: Optional. True, if the bot can send and edit messages in the private chats that had incoming messages in the last 24 hours + :type can_reply: :obj:`bool` + + :param can_read_messages: Optional. True, if the bot can mark incoming private messages as read + :type can_read_messages: :obj:`bool` + + :param can_delete_outgoing_messages: Optional. True, if the bot can delete messages sent by the bot + :type can_delete_outgoing_messages: :obj:`bool` + + :param can_delete_all_messages: Optional. True, if the bot can delete all private messages in managed chats + :type can_delete_all_messages: :obj:`bool` + + :param can_edit_name: Optional. True, if the bot can edit the first and last name of the business account + :type can_edit_name: :obj:`bool` + + :param can_edit_bio: Optional. True, if the bot can edit the bio of the business account + :type can_edit_bio: :obj:`bool` + + :param can_edit_profile_photo: Optional. True, if the bot can edit the profile photo of the business account + :type can_edit_profile_photo: :obj:`bool` + + :param can_edit_username: Optional. True, if the bot can edit the username of the business account + :type can_edit_username: :obj:`bool` + + :param can_change_gift_settings: Optional. True, if the bot can change the privacy settings pertaining to gifts for the business account + :type can_change_gift_settings: :obj:`bool` + + :param can_view_gifts_and_stars: Optional. True, if the bot can view gifts and the amount of Telegram Stars owned by the business account + :type can_view_gifts_and_stars: :obj:`bool` + + :param can_convert_gifts_to_stars: Optional. True, if the bot can convert regular gifts owned by the business account to Telegram Stars + :type can_convert_gifts_to_stars: :obj:`bool` + + :param can_transfer_and_upgrade_gifts: Optional. True, if the bot can transfer and upgrade gifts owned by the business account + :type can_transfer_and_upgrade_gifts: :obj:`bool` + + :param can_transfer_stars: Optional. True, if the bot can transfer Telegram Stars received by the business account to its own account, or use them to upgrade and transfer gifts + :type can_transfer_stars: :obj:`bool` + + :param can_manage_stories: Optional. True, if the bot can post, edit and delete stories on behalf of the business account + :type can_manage_stories: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`BusinessBotRights` + """ + def __init__(self, can_reply=None, can_read_messages=None, can_delete_outgoing_messages=None, can_delete_all_messages=None, + can_edit_name=None, can_edit_bio=None, can_edit_profile_photo=None, can_edit_username=None, + can_change_gift_settings=None, can_view_gifts_and_stars=None, can_convert_gifts_to_stars=None, + can_transfer_and_upgrade_gifts=None, can_transfer_stars=None, can_manage_stories=None, **kwargs): + self.can_reply: Optional[bool] = can_reply + self.can_read_messages: Optional[bool] = can_read_messages + self.can_delete_outgoing_messages: Optional[bool] = can_delete_outgoing_messages + self.can_delete_all_messages: Optional[bool] = can_delete_all_messages + self.can_edit_name: Optional[bool] = can_edit_name + self.can_edit_bio: Optional[bool] = can_edit_bio + self.can_edit_profile_photo: Optional[bool] = can_edit_profile_photo + self.can_edit_username: Optional[bool] = can_edit_username + self.can_change_gift_settings: Optional[bool] = can_change_gift_settings + self.can_view_gifts_and_stars: Optional[bool] = can_view_gifts_and_stars + self.can_convert_gifts_to_stars: Optional[bool] = can_convert_gifts_to_stars + self.can_transfer_and_upgrade_gifts: Optional[bool] = can_transfer_and_upgrade_gifts + self.can_transfer_stars: Optional[bool] = can_transfer_stars + self.can_manage_stories: Optional[bool] = can_manage_stories + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + From 805c78f7ae0482215c475f572cd3e7faf03f3b30 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 12:28:11 +0400 Subject: [PATCH 414/480] Add business account methods --- telebot/__init__.py | 92 +++++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 33 ++++++++++++++ telebot/async_telebot.py | 92 +++++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 33 ++++++++++++++ 4 files changed, 250 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 2ac86cf06..c1a99dacb 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6377,6 +6377,98 @@ def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: :rtype: :obj:`bool` """ return apihelper.remove_chat_verification(self.token, chat_id) + + def read_business_message(self, business_connection_id: str, chat_id: Union[int, str], message_id: int) -> bool: + """ + Marks incoming message as read on behalf of a business account. Requires the can_read_messages business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#readbusinessmessage + + :param business_connection_id: Unique identifier of the business connection on behalf of which to read the message + :type business_connection_id: :obj:`str` + + :param chat_id: Unique identifier of the chat in which the message was received. The chat must have been active in the last 24 hours. + :type chat_id: :obj:`int` | :obj:`str` + + :param message_id: Unique identifier of the message to mark as read + :type message_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.read_business_message(self.token, business_connection_id, chat_id, message_id) + + def delete_business_messages(self, business_connection_id: str, message_ids: List[int]) -> bool: + """ + Delete messages on behalf of a business account. Requires the can_delete_outgoing_messages business bot right to delete messages sent by the bot itself, or the can_delete_all_messages business bot right to delete any message. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#deletebusinessmessages + + :param business_connection_id: Unique identifier of the business connection on behalf of which to delete the messages + :type business_connection_id: :obj:`str` + + :param message_ids: A JSON-serialized list of 1-100 identifiers of messages to delete. All messages must be from the same chat. See deleteMessage for limitations on which messages can be deleted + :type message_ids: :obj:`list` of :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.delete_business_messages(self.token, business_connection_id, message_ids) + + def set_business_account_name(self, business_connection_id: str, first_name: str, last_name: Optional[str]=None) -> bool: + """ + Changes the first and last name of a managed business account. Requires the can_change_name business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountname + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param first_name: The new value of the first name for the business account; 1-64 characters + :type first_name: :obj:`str` + + :param last_name: The new value of the last name for the business account; 0-64 characters + :type last_name: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.set_business_account_name(self.token, business_connection_id, first_name, last_name) + + def set_business_account_username(self, business_connection_id: str, username: Optional[str]=None) -> bool: + """ + Changes the username of a managed business account. Requires the can_change_username business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountusername + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param username: The new value of the username for the business account; 0-32 characters + :type username: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + + """ + return apihelper.set_business_account_username(self.token, business_connection_id, username) + + def set_business_account_bio(self, business_connection_id: str, bio: Optional[str]=None) -> bool: + """ + Changes the bio of a managed business account. Requires the can_change_bio business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountbio + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param bio: The new value of the bio for the business account; 0-140 characters + :type bio: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.set_business_account_bio(self.token, business_connection_id, bio) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 879dfdec5..2fcb6b729 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1992,6 +1992,39 @@ def remove_chat_verification(token, chat_id): payload = {'chat_id': chat_id} return _make_request(token, method_url, params=payload, method='post') + +def read_business_message(token, business_connection_id, chat_id, message_id): + method_url = 'readBusinessMessage' + payload = {'business_connection_id': business_connection_id, 'chat_id': chat_id, 'message_id': message_id} + return _make_request(token, method_url, params=payload, method='post') + + +def delete_business_messages(token, business_connection_id, message_ids): + method_url = 'deleteBusinessMessages' + payload = {'business_connection_id': business_connection_id, 'message_ids': json.dumps(message_ids)} + return _make_request(token, method_url, params=payload, method='post') + + +def set_business_account_name(token, business_connection_id, first_name, last_name=None): + method_url = 'setBusinessAccountName' + payload = {'business_connection_id': business_connection_id, 'first_name': first_name} + if last_name: + payload['last_name'] = last_name + return _make_request(token, method_url, params=payload, method='post') + + +def set_business_account_username(token, business_connection_id, username): + method_url = 'setBusinessAccountUsername' + payload = {'business_connection_id': business_connection_id, 'username': username} + return _make_request(token, method_url, params=payload, method='post') + + +def set_business_account_bio(token, business_connection_id, bio): + method_url = 'setBusinessAccountBio' + payload = {'business_connection_id': business_connection_id, 'bio': bio} + return _make_request(token, method_url, params=payload, method='post') + + def set_sticker_emoji_list(token, sticker, emoji_list): method_url = 'setStickerEmojiList' payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index bc251220a..e8815232a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7835,6 +7835,98 @@ async def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: """ return await asyncio_helper.remove_chat_verification(self.token, chat_id) + async def read_business_message(self, business_connection_id: str, chat_id: Union[int, str], message_id: int) -> bool: + """ + Marks incoming message as read on behalf of a business account. Requires the can_read_messages business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#readbusinessmessage + + :param business_connection_id: Unique identifier of the business connection on behalf of which to read the message + :type business_connection_id: :obj:`str` + + :param chat_id: Unique identifier of the chat in which the message was received. The chat must have been active in the last 24 hours. + :type chat_id: :obj:`int` | :obj:`str` + + :param message_id: Unique identifier of the message to mark as read + :type message_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.read_business_message(self.token, business_connection_id, chat_id, message_id) + + async def delete_business_messages(self, business_connection_id: str, message_ids: List[int]) -> bool: + """ + Delete messages on behalf of a business account. Requires the can_delete_outgoing_messages business bot right to delete messages sent by the bot itself, or the can_delete_all_messages business bot right to delete any message. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#deletebusinessmessages + + :param business_connection_id: Unique identifier of the business connection on behalf of which to delete the messages + :type business_connection_id: :obj:`str` + + :param message_ids: A JSON-serialized list of 1-100 identifiers of messages to delete. All messages must be from the same chat. See deleteMessage for limitations on which messages can be deleted + :type message_ids: :obj:`list` of :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.delete_business_messages(self.token, business_connection_id, message_ids) + + async def set_business_account_name(self, business_connection_id: str, first_name: str, last_name: Optional[str]=None) -> bool: + """ + Changes the first and last name of a managed business account. Requires the can_change_name business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountname + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param first_name: The new value of the first name for the business account; 1-64 characters + :type first_name: :obj:`str` + + :param last_name: The new value of the last name for the business account; 0-64 characters + :type last_name: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.set_business_account_name(self.token, business_connection_id, first_name, last_name) + + async def set_business_account_username(self, business_connection_id: str, username: Optional[str]=None) -> bool: + """ + Changes the username of a managed business account. Requires the can_change_username business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountusername + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param username: The new value of the username for the business account; 0-32 characters + :type username: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + + """ + return await asyncio_helper.set_business_account_username(self.token, business_connection_id, username) + + async def set_business_account_bio(self, business_connection_id: str, bio: Optional[str]=None) -> bool: + """ + Changes the bio of a managed business account. Requires the can_change_bio business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountbio + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param bio: The new value of the bio for the business account; 0-140 characters + :type bio: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.set_business_account_bio(self.token, business_connection_id, bio) + async def get_available_gifts(self) -> types.Gifts: """ Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 99937ff63..c082509ae 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1972,6 +1972,39 @@ async def remove_chat_verification(token, chat_id): payload = {'chat_id': chat_id} return await _process_request(token, method_url, params=payload, method='post') + +async def read_business_message(token, business_connection_id, chat_id, message_id): + method_url = 'readBusinessMessage' + payload = {'business_connection_id': business_connection_id, 'chat_id': chat_id, 'message_id': message_id} + return await _process_request(token, method_url, params=payload, method='post') + + +async def delete_business_messages(token, business_connection_id, message_ids): + method_url = 'deleteBusinessMessages' + payload = {'business_connection_id': business_connection_id, 'message_ids': json.dumps(message_ids)} + return await _process_request(token, method_url, params=payload, method='post') + + +async def set_business_account_name(token, business_connection_id, first_name, last_name=None): + method_url = 'setBusinessAccountName' + payload = {'business_connection_id': business_connection_id, 'first_name': first_name} + if last_name: + payload['last_name'] = last_name + return await _process_request(token, method_url, params=payload, method='post') + + +async def set_business_account_username(token, business_connection_id, username): + method_url = 'setBusinessAccountUsername' + payload = {'business_connection_id': business_connection_id, 'username': username} + return await _process_request(token, method_url, params=payload, method='post') + + +async def set_business_account_bio(token, business_connection_id, bio): + method_url = 'setBusinessAccountBio' + payload = {'business_connection_id': business_connection_id, 'bio': bio} + return await _process_request(token, method_url, params=payload, method='post') + + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) From 1d32718bd7e00ef53ae2ca32bd61c1e846df5768 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 13:11:38 +0400 Subject: [PATCH 415/480] Added AcceptedGiftTypes and set_business_account_gift_settings --- telebot/__init__.py | 22 ++++++++++++++++++ telebot/apihelper.py | 5 ++++ telebot/async_telebot.py | 22 ++++++++++++++++++ telebot/asyncio_helper.py | 5 ++++ telebot/types.py | 49 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index c1a99dacb..afb063588 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6469,6 +6469,28 @@ def set_business_account_bio(self, business_connection_id: str, bio: Optional[st :rtype: :obj:`bool` """ return apihelper.set_business_account_bio(self.token, business_connection_id, bio) + + def set_business_account_gift_settings( + self, business_connection_id: str, show_gift_button: bool, accepted_gift_types: types.AcceptedGiftTypes) -> bool: + """ + Changes the privacy settings pertaining to incoming gifts in a managed business account. Requires the can_change_gift_settings business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountgiftsettings + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param show_gift_button: Pass True, if a button for sending a gift to the user or by the business account must always be shown in the input field + :type show_gift_button: :obj:`bool` + + :param accepted_gift_types: Types of gifts accepted by the business account + :type accepted_gift_types: :class:`telebot.types.AcceptedGiftTypes` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) + def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 2fcb6b729..979b5b7dc 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2025,6 +2025,11 @@ def set_business_account_bio(token, business_connection_id, bio): return _make_request(token, method_url, params=payload, method='post') +def set_business_account_gift_settings(token, business_connection_id, show_gift_button, accepted_gift_types): + method_url = 'setBusinessAccountGiftSettings' + payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, 'accepted_gift_types': json.dumps(accepted_gift_types)} + return _make_request(token, method_url, params=payload, method='post') + def set_sticker_emoji_list(token, sticker, emoji_list): method_url = 'setStickerEmojiList' payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index e8815232a..355d9791a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7927,6 +7927,27 @@ async def set_business_account_bio(self, business_connection_id: str, bio: Optio """ return await asyncio_helper.set_business_account_bio(self.token, business_connection_id, bio) + async def set_business_account_gift_settings( + self, business_connection_id: str, show_gift_button: bool, accepted_gift_types: types.AcceptedGiftTypes) -> bool: + """ + Changes the privacy settings pertaining to incoming gifts in a managed business account. Requires the can_change_gift_settings business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountgiftsettings + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param show_gift_button: Pass True, if a button for sending a gift to the user or by the business account must always be shown in the input field + :type show_gift_button: :obj:`bool` + + :param accepted_gift_types: Types of gifts accepted by the business account + :type accepted_gift_types: :class:`telebot.types.AcceptedGiftTypes` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) + async def get_available_gifts(self) -> types.Gifts: """ Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. @@ -7938,6 +7959,7 @@ async def get_available_gifts(self) -> types.Gifts: """ return types.Gifts.de_json(await asyncio_helper.get_available_gifts(self.token)) + async def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, sticker: types.InputSticker) -> bool: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index c082509ae..25d6658ee 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2004,6 +2004,11 @@ async def set_business_account_bio(token, business_connection_id, bio): payload = {'business_connection_id': business_connection_id, 'bio': bio} return await _process_request(token, method_url, params=payload, method='post') +async def set_business_account_gift_settings(token, business_connection_id, show_gift_button, accepted_gift_types): + method_url = 'setBusinessAccountGiftSettings' + payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, 'accepted_gift_types': json.dumps(accepted_gift_types)} + return await _process_request(token, method_url, params=payload, method='post') + async def get_available_gifts(token): method_url = 'getAvailableGifts' diff --git a/telebot/types.py b/telebot/types.py index 6b561505c..653d754e5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11354,4 +11354,53 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) + + +class AcceptedGiftTypes(JsonDeserializable, JsonSerializable): + """ + This object describes the types of gifts that can be gifted to a user or a chat. + + Telegram documentation: https://core.telegram.org/bots/api#acceptedgifttypes + + :param unlimited_gifts: True, if unlimited regular gifts are accepted + :type unlimited_gifts: :obj:`bool` + + :param limited_gifts: True, if limited regular gifts are accepted + :type limited_gifts: :obj:`bool` + + :param unique_gifts: True, if unique gifts or gifts that can be upgraded to unique for free are accepted + :type unique_gifts: :obj:`bool` + + :param premium_subscription: True, if a Telegram Premium subscription is accepted + :type premium_subscription: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`AcceptedGiftTypes` + """ + def __init__(self, unlimited_gifts: Optional[bool] = None, limited_gifts: Optional[bool] = None, + unique_gifts: Optional[bool] = None, premium_subscription: Optional[bool] = None, **kwargs): + self.unlimited_gifts: Optional[bool] = unlimited_gifts + self.limited_gifts: Optional[bool] = limited_gifts + self.unique_gifts: Optional[bool] = unique_gifts + self.premium_subscription: Optional[bool] = premium_subscription + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = {} + if self.unlimited_gifts is not None: + data['unlimited_gifts'] = self.unlimited_gifts + if self.limited_gifts is not None: + data['limited_gifts'] = self.limited_gifts + if self.unique_gifts is not None: + data['unique_gifts'] = self.unique_gifts + if self.premium_subscription is not None: + data['premium_subscription'] = self.premium_subscription + return data + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) From 3e0f06a1bd7f559430a77b3f306906c5c0f923e5 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 13:16:17 +0400 Subject: [PATCH 416/480] Add get_business_account_star_balance --- telebot/__init__.py | 18 +++++++++++++++++- telebot/apihelper.py | 4 ++++ telebot/async_telebot.py | 16 ++++++++++++++++ telebot/asyncio_helper.py | 5 +++++ telebot/types.py | 25 +++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index afb063588..c3b400f49 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6491,7 +6491,23 @@ def set_business_account_gift_settings( """ return apihelper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) - + + def get_business_account_star_balance(self, business_connection_id: str) -> types.StarAmount: + """ + Returns the amount of Telegram Stars owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns StarAmount on success. + + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountstarbalance + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :return: On success, a StarAmount object is returned. + :rtype: :class:`telebot.types.StarAmount` + """ + return types.StarAmount.de_json( + apihelper.get_business_account_star_balance(self.token, business_connection_id) + ) + def get_available_gifts(self) -> types.Gifts: """ Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 979b5b7dc..1b7335065 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2035,6 +2035,10 @@ def set_sticker_emoji_list(token, sticker, emoji_list): payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)} return _make_request(token, method_url, params=payload, method='post') +def get_business_account_star_balance(token, business_connection_id): + method_url = 'getBusinessAccountStarBalance' + payload = {'business_connection_id': business_connection_id} + return _make_request(token, method_url, params=payload) def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 355d9791a..c60bc458f 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7948,6 +7948,22 @@ async def set_business_account_gift_settings( """ return await asyncio_helper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) + async def get_business_account_star_balance(self, business_connection_id: str) -> types.StarAmount: + """ + Returns the amount of Telegram Stars owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns StarAmount on success. + + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountstarbalance + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :return: On success, a StarAmount object is returned. + :rtype: :class:`telebot.types.StarAmount` + """ + return types.StarAmount.de_json( + await asyncio_helper.get_business_account_star_balance(self.token, business_connection_id) + ) + async def get_available_gifts(self) -> types.Gifts: """ Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 25d6658ee..54733e254 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2009,6 +2009,11 @@ async def set_business_account_gift_settings(token, business_connection_id, show payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, 'accepted_gift_types': json.dumps(accepted_gift_types)} return await _process_request(token, method_url, params=payload, method='post') +async def get_business_account_star_balance(token, business_connection_id): + method_url = 'getBusinessAccountStarBalance' + payload = {'business_connection_id': business_connection_id} + return _process_request(token, method_url, params=payload) + async def get_available_gifts(token): method_url = 'getAvailableGifts' diff --git a/telebot/types.py b/telebot/types.py index 653d754e5..62107e91f 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11403,4 +11403,29 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) + + +class StarAmount(JsonDeserializable): + """ + Describes an amount of Telegram Stars. + + Telegram documentation: https://core.telegram.org/bots/api#staramount + + :param amount: Integer amount of Telegram Stars, rounded to 0; can be negative + :type amount: :obj:`int` + + :param nanostar_amount: Optional. The number of 1/1000000000 shares of Telegram Stars; from -999999999 to 999999999; can be negative if and only if amount is non-positive + :type nanostar_amount: :obj:`int` + + :return: Instance of the class + :rtype: :class:`StarAmount` + """ + def __init__(self, amount, nanostar_amount=None, **kwargs): + self.amount: int = amount + self.nanostar_amount: Optional[int] = nanostar_amount + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) From af858de87f4f9067ad012edb57da8df13ce6c260 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 13:20:01 +0400 Subject: [PATCH 417/480] Added transfer_business_account_stars --- README.md | 2 +- telebot/__init__.py | 17 +++++++++++++++++ telebot/apihelper.py | 5 +++++ telebot/async_telebot.py | 18 ++++++++++++++++++ telebot/asyncio_helper.py | 4 ++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a23b5c330..262fc2beb 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

diff --git a/telebot/__init__.py b/telebot/__init__.py index c3b400f49..241fc2fe3 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6507,6 +6507,23 @@ def get_business_account_star_balance(self, business_connection_id: str) -> type return types.StarAmount.de_json( apihelper.get_business_account_star_balance(self.token, business_connection_id) ) + + def transfer_business_account_stars(self, business_connection_id: str, star_count: int) -> bool: + """ + Transfers Telegram Stars from the business account balance to the bot's balance. Requires the can_transfer_stars business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#transferbusinessaccountstars + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param star_count: Number of Telegram Stars to transfer; 1-10000 + :type star_count: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.transfer_business_account_stars(self.token, business_connection_id, star_count) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 1b7335065..b413f5b6e 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2040,6 +2040,11 @@ def get_business_account_star_balance(token, business_connection_id): payload = {'business_connection_id': business_connection_id} return _make_request(token, method_url, params=payload) +def transfer_business_account_stars(token, business_connection_id, star_count): + method_url = 'transferBusinessAccountStars' + payload = {'business_connection_id': business_connection_id, 'star_count': star_count} + return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index c60bc458f..845ab6028 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7963,6 +7963,24 @@ async def get_business_account_star_balance(self, business_connection_id: str) - return types.StarAmount.de_json( await asyncio_helper.get_business_account_star_balance(self.token, business_connection_id) ) + + async def transfer_business_account_stars(self, business_connection_id: str, star_count: int) -> bool: + """ + Transfers Telegram Stars from the business account balance to the bot's balance. Requires the can_transfer_stars business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#transferbusinessaccountstars + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param star_count: Number of Telegram Stars to transfer; 1-10000 + :type star_count: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.transfer_business_account_stars(self.token, business_connection_id, star_count) + async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 54733e254..0bd0559bc 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2014,6 +2014,10 @@ async def get_business_account_star_balance(token, business_connection_id): payload = {'business_connection_id': business_connection_id} return _process_request(token, method_url, params=payload) +async def transfer_business_account_stars(token, business_connection_id, star_count): + method_url = 'transferBusinessAccountStars' + payload = {'business_connection_id': business_connection_id, 'star_count': star_count} + return await _process_request(token, method_url, params=payload, method='post') async def get_available_gifts(token): method_url = 'getAvailableGifts' From c012a59086110a4a7e64f22f611fc4040452c35a Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 13:48:50 +0400 Subject: [PATCH 418/480] Added get_business_account_gifts, OwnedGiftRegular, OwnedGiftUnique, OwnedGifts, UniqueGift, OwnedGift, UniqueGiftModel, UniqueGiftSymbol, UniqueGiftBackdrop, UniqueGiftBackdropColors --- telebot/__init__.py | 59 +++++++ telebot/apihelper.py | 23 +++ telebot/async_telebot.py | 58 +++++++ telebot/asyncio_helper.py | 23 +++ telebot/types.py | 347 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 510 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 241fc2fe3..c47d99919 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6524,6 +6524,65 @@ def transfer_business_account_stars(self, business_connection_id: str, star_coun :rtype: :obj:`bool` """ return apihelper.transfer_business_account_stars(self.token, business_connection_id, star_count) + + def get_business_account_gifts( + self, business_connection_id: str, + exclude_unsaved: Optional[bool]=None, + exclude_saved: Optional[bool]=None, + exclude_unlimited: Optional[bool]=None, + exclude_limited: Optional[bool]=None, + exclude_unique: Optional[bool]=None, + sort_by_price: Optional[bool]=None, + offset: Optional[str]=None, + limit: Optional[int]=None) -> types.OwnedGifts: + """ + Returns the gifts received and owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns OwnedGifts on success. + + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountgifts + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param exclude_unsaved: Pass True to exclude gifts that aren't saved to the account's profile page + :type exclude_unsaved: :obj:`bool` + + :param exclude_saved: Pass True to exclude gifts that are saved to the account's profile page + :type exclude_saved: :obj:`bool` + + :param exclude_unlimited: Pass True to exclude gifts that can be purchased an unlimited number of times + :type exclude_unlimited: :obj:`bool` + + :param exclude_limited: Pass True to exclude gifts that can be purchased a limited number of times + :type exclude_limited: :obj:`bool` + + :param exclude_unique: Pass True to exclude unique gifts + :type exclude_unique: :obj:`bool` + + :param sort_by_price: Pass True to sort results by gift price instead of send date. Sorting is applied before pagination. + :type sort_by_price: :obj:`bool` + + :param offset: Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results + :type offset: :obj:`str` + + :param limit: The maximum number of gifts to be returned; 1-100. Defaults to 100 + :type limit: :obj:`int` + + :return: On success, a OwnedGifts object is returned. + :rtype: :class:`telebot.types.OwnedGifts` + """ + return types.OwnedGifts.de_json( + apihelper.get_business_account_gifts( + self.token, business_connection_id, + exclude_unsaved=exclude_unsaved, + exclude_saved=exclude_saved, + exclude_unlimited=exclude_unlimited, + exclude_limited=exclude_limited, + exclude_unique=exclude_unique, + sort_by_price=sort_by_price, + offset=offset, + limit=limit + ) + ) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index b413f5b6e..f4f9545be 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2045,6 +2045,29 @@ def transfer_business_account_stars(token, business_connection_id, star_count): payload = {'business_connection_id': business_connection_id, 'star_count': star_count} return _make_request(token, method_url, params=payload, method='post') +def get_business_account_gifts(token, business_connection_id, exclude_unsaved=None, exclude_saved=None, + exclude_unlimited=None, exclude_limited=None, exclude_unique=None, + sort_by_price=None, offset=None, limit=None): + method_url = 'getBusinessAccountGifts' + payload = {'business_connection_id': business_connection_id} + if exclude_unsaved is not None: + payload['exclude_unsaved'] = exclude_unsaved + if exclude_saved is not None: + payload['exclude_saved'] = exclude_saved + if exclude_unlimited is not None: + payload['exclude_unlimited'] = exclude_unlimited + if exclude_limited is not None: + payload['exclude_limited'] = exclude_limited + if exclude_unique is not None: + payload['exclude_unique'] = exclude_unique + if sort_by_price is not None: + payload['sort_by_price'] = sort_by_price + if offset is not None: + payload['offset'] = offset + if limit is not None: + payload['limit'] = limit + return _make_request(token, method_url, params=payload) + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 845ab6028..7ce6c03e7 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7980,7 +7980,65 @@ async def transfer_business_account_stars(self, business_connection_id: str, sta :rtype: :obj:`bool` """ return await asyncio_helper.transfer_business_account_stars(self.token, business_connection_id, star_count) + + async def get_business_account_gifts( + self, business_connection_id: str, + exclude_unsaved: Optional[bool]=None, + exclude_saved: Optional[bool]=None, + exclude_unlimited: Optional[bool]=None, + exclude_limited: Optional[bool]=None, + exclude_unique: Optional[bool]=None, + sort_by_price: Optional[bool]=None, + offset: Optional[str]=None, + limit: Optional[int]=None) -> types.OwnedGifts: + """ + Returns the gifts received and owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns OwnedGifts on success. + + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountgifts + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param exclude_unsaved: Pass True to exclude gifts that aren't saved to the account's profile page + :type exclude_unsaved: :obj:`bool` + + :param exclude_saved: Pass True to exclude gifts that are saved to the account's profile page + :type exclude_saved: :obj:`bool` + + :param exclude_unlimited: Pass True to exclude gifts that can be purchased an unlimited number of times + :type exclude_unlimited: :obj:`bool` + :param exclude_limited: Pass True to exclude gifts that can be purchased a limited number of times + :type exclude_limited: :obj:`bool` + + :param exclude_unique: Pass True to exclude unique gifts + :type exclude_unique: :obj:`bool` + + :param sort_by_price: Pass True to sort results by gift price instead of send date. Sorting is applied before pagination. + :type sort_by_price: :obj:`bool` + + :param offset: Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results + :type offset: :obj:`str` + + :param limit: The maximum number of gifts to be returned; 1-100. Defaults to 100 + :type limit: :obj:`int` + + :return: On success, a OwnedGifts object is returned. + :rtype: :class:`telebot.types.OwnedGifts` + """ + return types.OwnedGifts.de_json( + await asyncio_helper.get_business_account_gifts( + self.token, business_connection_id, + exclude_unsaved=exclude_unsaved, + exclude_saved=exclude_saved, + exclude_unlimited=exclude_unlimited, + exclude_limited=exclude_limited, + exclude_unique=exclude_unique, + sort_by_price=sort_by_price, + offset=offset, + limit=limit + ) + ) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 0bd0559bc..3c587d7bd 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2019,6 +2019,29 @@ async def transfer_business_account_stars(token, business_connection_id, star_co payload = {'business_connection_id': business_connection_id, 'star_count': star_count} return await _process_request(token, method_url, params=payload, method='post') +async def get_business_account_gifts(token, business_connection_id, exclude_unsaved=None, exclude_saved=None, + exclude_unlimited=None, exclude_limited=None, exclude_unique=None, + sort_by_price=None, offset=None, limit=None): + method_url = 'getBusinessAccountGifts' + payload = {'business_connection_id': business_connection_id} + if exclude_unsaved is not None: + payload['exclude_unsaved'] = exclude_unsaved + if exclude_saved is not None: + payload['exclude_saved'] = exclude_saved + if exclude_unlimited is not None: + payload['exclude_unlimited'] = exclude_unlimited + if exclude_limited is not None: + payload['exclude_limited'] = exclude_limited + if exclude_unique is not None: + payload['exclude_unique'] = exclude_unique + if sort_by_price is not None: + payload['sort_by_price'] = sort_by_price + if offset is not None: + payload['offset'] = offset + if limit is not None: + payload['limit'] = limit + return await _process_request(token, method_url, params=payload) + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) diff --git a/telebot/types.py b/telebot/types.py index 62107e91f..8b1fc3a39 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11429,3 +11429,350 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) + +class OwnedGift(JsonDeserializable): + """ + This object describes a gift received and owned by a user or a chat. Currently, it can be one of + OwnedGiftRegular + OwnedGiftUnique + + Telegram documentation: https://core.telegram.org/bots/api#ownedgift + """ + + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if obj["type"] == "regular": + return OwnedGiftRegular.de_json(obj) + elif obj["type"] == "unique": + return OwnedGiftUnique.de_json(obj) + +class OwnedGiftRegular(OwnedGift): + """ + This object describes a regular gift owned by a user or a chat. + + Telegram documentation: https://core.telegram.org/bots/api#ownedgiftregular + + :param type: Type of the gift, always “regular” + :type type: :obj:`str` + + :param gift: Information about the regular gift + :type gift: :class:`Gift` + + :param owned_gift_id: Optional. Unique identifier of the gift for the bot; for gifts received on behalf of business accounts only + :type owned_gift_id: :obj:`str` + + :param sender_user: Optional. Sender of the gift if it is a known user + :type sender_user: :class:`User` + + :param send_date: Date the gift was sent in Unix time + :type send_date: :obj:`int` + + :param text: Optional. Text of the message that was added to the gift + :type text: :obj:`str` + + :param entities: Optional. Special entities that appear in the text + :type entities: :obj:`list` of :class:`MessageEntity` + + :param is_private: Optional. True, if the sender and gift text are shown only to the gift receiver; otherwise, everyone will be able to see them + :type is_private: :obj:`bool` + + :param is_saved: Optional. True, if the gift is displayed on the account's profile page; for gifts received on behalf of business accounts only + :type is_saved: :obj:`bool` + + :param can_be_upgraded: Optional. True, if the gift can be upgraded to a unique gift; for gifts received on behalf of business accounts only + :type can_be_upgraded: :obj:`bool` + + :param was_refunded: Optional. True, if the gift was refunded and isn't available anymore + :type was_refunded: :obj:`bool` + + :param convert_star_count: Optional. Number of Telegram Stars that can be claimed by the receiver instead of the gift; omitted if the gift cannot be converted to Telegram Stars + :type convert_star_count: :obj:`int` + + :param prepaid_upgrade_star_count: Optional. Number of Telegram Stars that were paid by the sender for the ability to upgrade the gift + :type prepaid_upgrade_star_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`OwnedGiftRegular` + """ + def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=None, text=None, entities=None, + is_private=None, is_saved=None, can_be_upgraded=None, was_refunded=None, convert_star_count=None, + prepaid_upgrade_star_count=None, **kwargs): + self.type: str = type + self.gift: Gift = gift + self.owned_gift_id: Optional[str] = owned_gift_id + self.sender_user: Optional[User] = sender_user + self.send_date: Optional[int] = send_date + self.text: Optional[str] = text + self.entities: Optional[List[MessageEntity]] = entities + self.is_private: Optional[bool] = is_private + self.is_saved: Optional[bool] = is_saved + self.can_be_upgraded: Optional[bool] = can_be_upgraded + self.was_refunded: Optional[bool] = was_refunded + self.convert_star_count: Optional[int] = convert_star_count + self.prepaid_upgrade_star_count: Optional[int] = prepaid_upgrade_star_count + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['gift'] = Gift.de_json(obj['gift']) + if 'sender_user' in obj: + obj['sender_user'] = User.de_json(obj['sender_user']) + if 'entities' in obj: + obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] + return cls(**obj) + +class OwnedGiftUnique(OwnedGift): + """ + This object describes a unique gift owned by a user or a chat. + + Telegram documentation: https://core.telegram.org/bots/api#ownedgiftunique + + :param type: Type of the gift, always “unique” + :type type: :obj:`str` + + :param gift: Information about the unique gift + :type gift: :class:`UniqueGift` + + :param owned_gift_id: Optional. Unique identifier of the received gift for the bot; for gifts received on behalf of business accounts only + :type owned_gift_id: :obj:`str` + + :param sender_user: Optional. Sender of the gift if it is a known user + :type sender_user: :class:`User` + + :param send_date: Date the gift was sent in Unix time + :type send_date: :obj:`int` + + :param is_saved: Optional. True, if the gift is displayed on the account's profile page; for gifts received on behalf of business accounts only + :type is_saved: :obj:`bool` + + :param can_be_transferred: Optional. True, if the gift can be transferred to another owner; for gifts received on behalf of business accounts only + :type can_be_transferred: :obj:`bool` + + :param transfer_star_count: Optional. Number of Telegram Stars that must be paid to transfer the gift; omitted if the bot cannot transfer the gift + :type transfer_star_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`OwnedGiftUnique` + """ + def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=None, is_saved=None, + can_be_transferred=None, transfer_star_count=None, **kwargs): + self.type: str = type + self.gift: UniqueGift = gift + self.owned_gift_id: Optional[str] = owned_gift_id + self.sender_user: Optional[User] = sender_user + self.send_date: Optional[int] = send_date + self.is_saved: Optional[bool] = is_saved + self.can_be_transferred: Optional[bool] = can_be_transferred + self.transfer_star_count: Optional[int] = transfer_star_count + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['gift'] = UniqueGift.de_json(obj['gift']) + if 'sender_user' in obj: + obj['sender_user'] = User.de_json(obj['sender_user']) + return cls(**obj) + + +class OwnedGifts(JsonDeserializable): + """ + Contains the list of gifts received and owned by a user or a chat. + + Telegram documentation: https://core.telegram.org/bots/api#ownedgifts + + :param total_count: The total number of gifts owned by the user or the chat + :type total_count: :obj:`int` + + :param gifts: The list of gifts + :type gifts: :obj:`list` of :class:`OwnedGift` + + :param next_offset: Optional. Offset for the next request. If empty, then there are no more results + :type next_offset: :obj:`str` + + :return: Instance of the class + :rtype: :class:`OwnedGifts` + + """ + def __init__(self, total_count, gifts, next_offset=None, **kwargs): + self.total_count: int = total_count + self.gifts: List[OwnedGift] = gifts + self.next_offset: Optional[str] = next_offset + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['gifts'] = [OwnedGift.de_json(gift) for gift in obj['gifts']] + return cls(**obj) + + + +class UniqueGift(JsonDeserializable): + """ + This object describes a unique gift that was upgraded from a regular gift. + + Telegram documentation: https://core.telegram.org/bots/api#uniquegift + + :param base_name: Human-readable name of the regular gift from which this unique gift was upgraded + :type base_name: :obj:`str` + + :param name: Unique name of the gift. This name can be used in https://t.me/nft/... links and story areas + :type name: :obj:`str` + + :param number: Unique number of the upgraded gift among gifts upgraded from the same regular gift + :type number: :obj:`int` + + :param model: Model of the gift + :type model: :class:`UniqueGiftModel` + + :param symbol: Symbol of the gift + :type symbol: :class:`UniqueGiftSymbol` + + :param backdrop: Backdrop of the gift + :type backdrop: :class:`UniqueGiftBackdrop` + + :return: Instance of the class + :rtype: :class:`UniqueGift` + """ + def __init__(self, base_name, name, number, model, symbol, backdrop, **kwargs): + self.base_name: str = base_name + self.name: str = name + self.number: int = number + self.model: UniqueGiftModel = model + self.symbol: UniqueGiftSymbol = symbol + self.backdrop: UniqueGiftBackdrop = backdrop + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['model'] = UniqueGiftModel.de_json(obj['model']) + obj['symbol'] = UniqueGiftSymbol.de_json(obj['symbol']) + obj['backdrop'] = UniqueGiftBackdrop.de_json(obj['backdrop']) + return cls(**obj) + + +class UniqueGiftModel(JsonDeserializable): + """ + This object describes the model of a unique gift. + + Telegram documentation: https://core.telegram.org/bots/api#uniquegiftmodel + + :param name: Name of the model + :type name: :obj:`str` + + :param sticker: The sticker that represents the unique gift + :type sticker: :class:`Sticker` + + :param rarity_per_mille: The number of unique gifts that receive this model for every 1000 gifts upgraded + :type rarity_per_mille: :obj:`int` + + :return: Instance of the class + :rtype: :class:`UniqueGiftModel` + + """ + def __init__(self, name, sticker, rarity_per_mille, **kwargs): + self.name: str = name + self.sticker: Sticker = sticker + self.rarity_per_mille: int = rarity_per_mille + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['sticker'] = Sticker.de_json(obj['sticker']) + return cls(**obj) + +class UniqueGiftSymbol(JsonDeserializable): + """ + This object describes the symbol shown on the pattern of a unique gift. + + Telegram documentation: https://core.telegram.org/bots/api#uniquegiftsymbol + + :param name: Name of the symbol + :type name: :obj:`str` + + :param sticker: The sticker that represents the unique gift + :type sticker: :class:`Sticker` + + :param rarity_per_mille: The number of unique gifts that receive this model for every 1000 gifts upgraded + :type rarity_per_mille: :obj:`int` + + :return: Instance of the class + :rtype: :class:`UniqueGiftSymbol` + """ + + def __init__(self, name, sticker, rarity_per_mille, **kwargs): + self.name: str = name + self.sticker: Sticker = sticker + self.rarity_per_mille: int = rarity_per_mille + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['sticker'] = Sticker.de_json(obj['sticker']) + return cls(**obj) + +class UniqueGiftBackdropColors(JsonDeserializable): + """ + This object describes the colors of the backdrop of a unique gift. + + Telegram documentation: https://core.telegram.org/bots/api#uniquegiftbackdropcolors + + :param center_color: The color in the center of the backdrop in RGB format + :type center_color: :obj:`int` + + :param edge_color: The color on the edges of the backdrop in RGB format + :type edge_color: :obj:`int` + + :param symbol_color: The color to be applied to the symbol in RGB format + :type symbol_color: :obj:`int` + + :param text_color: The color for the text on the backdrop in RGB format + :type text_color: :obj:`int` + + :return: Instance of the class + :rtype: :class:`UniqueGiftBackdropColors` + """ + def __init__(self, center_color, edge_color, symbol_color, text_color, **kwargs): + self.center_color: int = center_color + self.edge_color: int = edge_color + self.symbol_color: int = symbol_color + self.text_color: int = text_color + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) + +class UniqueGiftBackdrop(JsonDeserializable): + """ + This object describes the backdrop of a unique gift. + + Telegram documentation: https://core.telegram.org/bots/api#uniquegiftbackdrop + + :param name: Name of the backdrop + :type name: :obj:`str` + + :param colors: Colors of the backdrop + :type colors: :class:`UniqueGiftBackdropColors` + + :param rarity_per_mille: The number of unique gifts that receive this backdrop for every 1000 gifts upgraded + :type rarity_per_mille: :obj:`int` + + :return: Instance of the class + :rtype: :class:`UniqueGiftBackdrop` + """ + def __init__(self, name, colors, rarity_per_mille, **kwargs): + self.name: str = name + self.colors: UniqueGiftBackdropColors = colors + self.rarity_per_mille: int = rarity_per_mille + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['colors'] = UniqueGiftBackdropColors.de_json(obj['colors']) + return cls(**obj) + + + From 3d238a4a2a9eea85eed2d9f862d0ebcbe157c0fd Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 13:53:07 +0400 Subject: [PATCH 419/480] Added convert_gift_to_stars --- telebot/__init__.py | 17 +++++++++++++++++ telebot/apihelper.py | 6 ++++++ telebot/async_telebot.py | 17 +++++++++++++++++ telebot/asyncio_helper.py | 5 +++++ 4 files changed, 45 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index c47d99919..7476ff8fa 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6584,6 +6584,23 @@ def get_business_account_gifts( ) ) + def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id: str) -> bool: + """ + Converts a given regular gift to Telegram Stars. Requires the can_convert_gifts_to_stars business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#convertgifttostars + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param owned_gift_id: Unique identifier of the regular gift that should be converted to Telegram Stars + :type owned_gift_id: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) + def get_available_gifts(self) -> types.Gifts: """ Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. diff --git a/telebot/apihelper.py b/telebot/apihelper.py index f4f9545be..d18a6380a 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2068,6 +2068,12 @@ def get_business_account_gifts(token, business_connection_id, exclude_unsaved=No payload['limit'] = limit return _make_request(token, method_url, params=payload) + +def convert_gift_to_stars(token, business_connection_id, owned_gift_id): + method_url = 'convertGiftToStars' + payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id} + return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 7ce6c03e7..6b601e33a 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -8039,6 +8039,23 @@ async def get_business_account_gifts( limit=limit ) ) + + async def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id: str) -> bool: + """ + Converts a given regular gift to Telegram Stars. Requires the can_convert_gifts_to_stars business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#convertgifttostars + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param owned_gift_id: Unique identifier of the regular gift that should be converted to Telegram Stars + :type owned_gift_id: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 3c587d7bd..0e21a6978 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2042,6 +2042,11 @@ async def get_business_account_gifts(token, business_connection_id, exclude_unsa payload['limit'] = limit return await _process_request(token, method_url, params=payload) +async def convert_gift_to_stars(token, business_connection_id, owned_gift_id): + method_url = 'convertGiftToStars' + payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id} + return await _process_request(token, method_url, params=payload, method='post') + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) From 817f2ad79b697b4b459942e2cb9661dc8dcf755c Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 13:59:19 +0400 Subject: [PATCH 420/480] Added upgrade_gift and transfer_gift methods --- telebot/__init__.py | 65 +++++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 16 ++++++++++ telebot/async_telebot.py | 64 ++++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 16 ++++++++++ 4 files changed, 161 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 7476ff8fa..4a6dfc3d7 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6600,6 +6600,71 @@ def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id: str) :rtype: :obj:`bool` """ return apihelper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) + + def upgrade_gift( + self, business_connection_id: str, owned_gift_id: str, + keep_original_details: Optional[bool]=None, + star_count: Optional[int]=None) -> bool: + """ + Upgrades a given regular gift to a unique gift. Requires the can_transfer_and_upgrade_gifts business bot right. + Additionally requires the can_transfer_stars business bot right if the upgrade is paid. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#upgradegift + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param owned_gift_id: Unique identifier of the regular gift that should be upgraded to a unique one + :type owned_gift_id: :obj:`str` + + :param keep_original_details: Pass True to keep the original gift text, sender and receiver in the upgraded gift + :type keep_original_details: :obj:`bool` + + :param star_count: The amount of Telegram Stars that will be paid for the upgrade from the business account balance. + If gift.prepaid_upgrade_star_count > 0, then pass 0, otherwise, the can_transfer_stars business bot right is required and gift.upgrade_star_count must be passed. + :type star_count: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.upgrade_gift( + self.token, business_connection_id, owned_gift_id, + keep_original_details=keep_original_details, + star_count=star_count + ) + + def transfer_gift( + self, business_connection_id: str, owned_gift_id: str, + new_owner_chat_id: Union[int, str], + star_count: Optional[int]=None) -> bool: + """ + Transfers an owned unique gift to another user. Requires the can_transfer_and_upgrade_gifts business bot right. + Requires can_transfer_stars business bot right if the transfer is paid. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#transfergift + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param owned_gift_id: Unique identifier of the regular gift that should be transferred + :type owned_gift_id: :obj:`str` + + :param new_owner_chat_id: Unique identifier of the chat which will own the gift. The chat must be active in the last 24 hours. + :type new_owner_chat_id: :obj:`int` | :obj:`str` + + :param star_count: The amount of Telegram Stars that will be paid for the transfer from the business account balance. + If positive, then the can_transfer_stars business bot right is required. + :type star_count: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.transfer_gift( + self.token, business_connection_id, owned_gift_id, + new_owner_chat_id=new_owner_chat_id, + star_count=star_count + ) + def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d18a6380a..366fb9435 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2074,6 +2074,22 @@ def convert_gift_to_stars(token, business_connection_id, owned_gift_id): payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id} return _make_request(token, method_url, params=payload, method='post') +def upgrade_gift(token, business_connection_id, owned_gift_id, keep_original_details=None, star_count=None): + method_url = 'upgradeGift' + payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id} + if keep_original_details is not None: + payload['keep_original_details'] = keep_original_details + if star_count is not None: + payload['star_count'] = star_count + return _make_request(token, method_url, params=payload, method='post') + +def transfer_gift(token, business_connection_id, owned_gift_id, new_owner_chat_id, star_count=None): + method_url = 'transferGift' + payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id, 'new_owner_chat_id': new_owner_chat_id} + if star_count is not None: + payload['star_count'] = star_count + return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 6b601e33a..8c12e7891 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -8056,6 +8056,70 @@ async def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id :rtype: :obj:`bool` """ return await asyncio_helper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) + + async def upgrade_gift( + self, business_connection_id: str, owned_gift_id: str, + keep_original_details: Optional[bool]=None, + star_count: Optional[int]=None) -> bool: + """ + Upgrades a given regular gift to a unique gift. Requires the can_transfer_and_upgrade_gifts business bot right. + Additionally requires the can_transfer_stars business bot right if the upgrade is paid. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#upgradegift + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param owned_gift_id: Unique identifier of the regular gift that should be upgraded to a unique one + :type owned_gift_id: :obj:`str` + + :param keep_original_details: Pass True to keep the original gift text, sender and receiver in the upgraded gift + :type keep_original_details: :obj:`bool` + + :param star_count: The amount of Telegram Stars that will be paid for the upgrade from the business account balance. + If gift.prepaid_upgrade_star_count > 0, then pass 0, otherwise, the can_transfer_stars business bot right is required and gift.upgrade_star_count must be passed. + :type star_count: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.upgrade_gift( + self.token, business_connection_id, owned_gift_id, + keep_original_details=keep_original_details, + star_count=star_count + ) + + async def transfer_gift( + self, business_connection_id: str, owned_gift_id: str, + new_owner_chat_id: Union[int, str], + star_count: Optional[int]=None) -> bool: + """ + Transfers an owned unique gift to another user. Requires the can_transfer_and_upgrade_gifts business bot right. + Requires can_transfer_stars business bot right if the transfer is paid. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#transfergift + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param owned_gift_id: Unique identifier of the regular gift that should be transferred + :type owned_gift_id: :obj:`str` + + :param new_owner_chat_id: Unique identifier of the chat which will own the gift. The chat must be active in the last 24 hours. + :type new_owner_chat_id: :obj:`int` | :obj:`str` + + :param star_count: The amount of Telegram Stars that will be paid for the transfer from the business account balance. + If positive, then the can_transfer_stars business bot right is required. + :type star_count: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.transfer_gift( + self.token, business_connection_id, owned_gift_id, + new_owner_chat_id=new_owner_chat_id, + star_count=star_count + ) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 0e21a6978..f539bd04e 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2047,6 +2047,22 @@ async def convert_gift_to_stars(token, business_connection_id, owned_gift_id): payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id} return await _process_request(token, method_url, params=payload, method='post') +async def upgrade_gift(token, business_connection_id, owned_gift_id, keep_original_details=None, star_count=None): + method_url = 'upgradeGift' + payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id} + if keep_original_details is not None: + payload['keep_original_details'] = keep_original_details + if star_count is not None: + payload['star_count'] = star_count + return await _process_request(token, method_url, params=payload, method='post') + +async def transfer_gift(token, business_connection_id, owned_gift_id, new_owner_chat_id, star_count=None): + method_url = 'transferGift' + payload = {'business_connection_id': business_connection_id, 'owned_gift_id': owned_gift_id, 'new_owner_chat_id': new_owner_chat_id} + if star_count is not None: + payload['star_count'] = star_count + return await _process_request(token, method_url, params=payload, method='post') + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) From b47c73f00cd0bdb930db2281ebe5421c9f9b7cd3 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 14:19:50 +0400 Subject: [PATCH 421/480] Added InputStoryContent --- telebot/__init__.py | 1 + telebot/types.py | 90 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 4a6dfc3d7..075d9f6e0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -9651,3 +9651,4 @@ def _notify_command_handlers(self, handlers, new_messages, update_type): handlers=handlers, middlewares=middlewares, update_type=update_type) + diff --git a/telebot/types.py b/telebot/types.py index 8b1fc3a39..637599233 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11773,6 +11773,96 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['colors'] = UniqueGiftBackdropColors.de_json(obj['colors']) return cls(**obj) + +class InputStoryContent(JsonSerializable): + """ + This object describes the content of a story to post. Currently, it can be one of + InputStoryContentPhoto + InputStoryContentVideo + + Telegram documentation: https://core.telegram.org/bots/api#inputstorycontent + + """ + + +class InputStoryContentPhoto(InputStoryContent): + """ + This object describes a photo to post as a story. + + Telegram documentation: https://core.telegram.org/bots/api#inputstorycontentphoto + + :param photo: The photo to post as a story. The photo must be of the size 1080x1920 and must not exceed 10 MB. The photo can't be reused and can only be uploaded as a new file, so you can pass “attach://” if the photo was uploaded using multipart/form-data under . More information on Sending Files + :type photo: :obj:`str` + + :return: Instance of the class + :rtype: :class:`InputStoryContentPhoto` + """ + def __init__(self, photo: InputFile, **kwargs): + self.type: str = "photo" + self.photo: InputFile = photo + self._photo_name = service_utils.generate_random_token() + self._photo_dic = "attach://{}".format(self._photo_name) + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'type': self.type, + 'photo': self._photo_dic + } + return data + + def convert_input_story(self): + return self.to_json(), {self._photo_name: self.photo} +class InputStoryContentVideo(InputStoryContent): + """ + This object describes a video to post as a story. + + Telegram documentation: https://core.telegram.org/bots/api#inputstorycontentvideo + + :param video: The video to post as a story. The video must be of the size 720x1280, streamable, encoded with H.265 codec, with key frames added each second in the MPEG4 format, and must not exceed 30 MB. The video can't be reused and can only be uploaded as a new file, so you can pass “attach://” if the video was uploaded using multipart/form-data under . More information on Sending Files + :type video: :obj:`str` + + :param duration: Optional. Precise duration of the video in seconds; 0-60 + :type duration: :obj:`float` + + :param cover_frame_timestamp: Optional. Timestamp in seconds of the frame that will be used as the static cover for the story. Defaults to 0.0. + :type cover_frame_timestamp: :obj:`float` + + :param is_animation: Optional. Pass True if the video has no sound + :type is_animation: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`InputStoryContentVideo` + """ + def __init__(self, video: InputFile, duration: Optional[float] = None, cover_frame_timestamp: Optional[float] = None, + is_animation: Optional[bool] = None, **kwargs): + self.type: str = "video" + self.video: InputFile = video + self._video_name = service_utils.generate_random_token() + self._video_dic = "attach://{}".format(self._video_name) + self.duration: Optional[float] = duration + self.cover_frame_timestamp: Optional[float] = cover_frame_timestamp + self.is_animation: Optional[bool] = is_animation + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'type': self.type, + 'video': self._video_dic + } + if self.duration is not None: + data['duration'] = self.duration + if self.cover_frame_timestamp is not None: + data['cover_frame_timestamp'] = self.cover_frame_timestamp + if self.is_animation is not None: + data['is_animation'] = self.is_animation + return data + def convert_input_story(self): + return self.to_json(), {self._video_name: self.video} + From 17139098828a1105dca2452c101f1824f815f4fb Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 14:40:00 +0400 Subject: [PATCH 422/480] Stories --- telebot/types.py | 305 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 637599233..8745bfa66 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11866,3 +11866,308 @@ def convert_input_story(self): return self.to_json(), {self._video_name: self.video} +class StoryAreaPosition(JsonSerializable): + """ + Describes the position of a clickable area within a story. + + Telegram documentation: https://core.telegram.org/bots/api#storyareaposition + + :param x_percentage: The abscissa of the area's center, as a percentage of the media width + :type x_percentage: :obj:`float` + + :param y_percentage: The ordinate of the area's center, as a percentage of the media height + :type y_percentage: :obj:`float` + + :param width_percentage: The width of the area's rectangle, as a percentage of the media width + :type width_percentage: :obj:`float` + + :param height_percentage: The height of the area's rectangle, as a percentage of the media height + :type height_percentage: :obj:`float` + + :param rotation_angle: The clockwise rotation angle of the rectangle, in degrees; 0-360 + :type rotation_angle: :obj:`float` + + :param corner_radius_percentage: The radius of the rectangle corner rounding, as a percentage of the media width + :type corner_radius_percentage: :obj:`float` + + :return: Instance of the class + :rtype: :class:`StoryAreaPosition` + """ + def __init__(self, x_percentage: float, y_percentage: float, width_percentage: float, + height_percentage: float, rotation_angle: float, corner_radius_percentage: float, **kwargs): + self.x_percentage: float = x_percentage + self.y_percentage: float = y_percentage + self.width_percentage: float = width_percentage + self.height_percentage: float = height_percentage + self.rotation_angle: float = rotation_angle + self.corner_radius_percentage: float = corner_radius_percentage + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'x_percentage': self.x_percentage, + 'y_percentage': self.y_percentage, + 'width_percentage': self.width_percentage, + 'height_percentage': self.height_percentage, + 'rotation_angle': self.rotation_angle, + 'corner_radius_percentage': self.corner_radius_percentage + } + return data + + +class LocationAddress(JsonSerializable): + """ + Describes the physical address of a location. + + Telegram documentation: https://core.telegram.org/bots/api#locationaddress + + :param country_code: The two-letter ISO 3166-1 alpha-2 country code of the country where the location is located + :type country_code: :obj:`str` + + :param state: Optional. State of the location + :type state: :obj:`str` + + :param city: Optional. City of the location + :type city: :obj:`str` + + :param street: Optional. Street address of the location + :type street: :obj:`str` + + :return: Instance of the class + :rtype: :class:`LocationAddress` + """ + def __init__(self, country_code: str, state: Optional[str] = None, city: Optional[str] = None, + street: Optional[str] = None, **kwargs): + self.country_code: str = country_code + self.state: Optional[str] = state + self.city: Optional[str] = city + self.street: Optional[str] = street + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'country_code': self.country_code + } + if self.state is not None: + data['state'] = self.state + if self.city is not None: + data['city'] = self.city + if self.street is not None: + data['street'] = self.street + return data + +class StoryAreaType(JsonSerializable): + """ + Describes the type of a clickable area on a story. Currently, it can be one of + StoryAreaTypeLocation + StoryAreaTypeSuggestedReaction + StoryAreaTypeLink + StoryAreaTypeWeather + StoryAreaTypeUniqueGift + + Telegram documentation: https://core.telegram.org/bots/api#storyarea + + :return: Instance of the class + :rtype: :class:`StoryArea` + """ + + +class StoryAreaTypeLocation(StoryAreaType): + """ + Describes a story area pointing to a location. Currently, a story can have up to 10 location areas. + + Telegram documentation: https://core.telegram.org/bots/api#storyareatypelocation + + :param type: Type of the area, always “location” + :type type: :obj:`str` + + :param latitude: Location latitude in degrees + :type latitude: :obj:`float` + + :param longitude: Location longitude in degrees + :type longitude: :obj:`float` + + :param address: Location address + :type address: :class:`LocationAddress` + + :return: Instance of the class + :rtype: :class:`StoryAreaTypeLocation` + """ + def __init__(self,latitude: float, longitude: float, address: LocationAddress, **kwargs): + self.type: str = "location" + self.latitude: float = latitude + self.longitude: float = longitude + self.address: LocationAddress = address + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'type': self.type, + 'latitude': self.latitude, + 'longitude': self.longitude, + 'address': self.address.to_json() + } + return data + + +class StoryAreaTypeSuggestedReaction(StoryAreaType): + """ + Describes a story area pointing to a suggested reaction. Currently, a story can have up to 5 suggested reaction areas. + + Telegram documentation: https://core.telegram.org/bots/api#storyareatypesuggestedreaction + + :param type: Type of the area, always “suggested_reaction” + :type type: :obj:`str` + + :param reaction_type: Type of the reaction + :type reaction_type: :class:`ReactionType` + + :param is_dark: Optional. Pass True if the reaction area has a dark background + :type is_dark: :obj:`bool` + + :param is_flipped: Optional. Pass True if reaction area corner is flipped + :type is_flipped: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`StoryAreaTypeSuggestedReaction` + """ + def __init__(self, reaction_type: ReactionType, is_dark: Optional[bool] = None, is_flipped: Optional[bool] = None, **kwargs): + self.type: str = "suggested_reaction" + self.reaction_type: ReactionType = reaction_type + self.is_dark: Optional[bool] = is_dark + self.is_flipped: Optional[bool] = is_flipped + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'type': self.type, + 'reaction_type': self.reaction_type.to_json() + } + if self.is_dark is not None: + data['is_dark'] = self.is_dark + if self.is_flipped is not None: + data['is_flipped'] = self.is_flipped + return data + +class StoryAreaTypeLink(StoryAreaType): + """ + Describes a story area pointing to an HTTP or tg:// link. Currently, a story can have up to 3 link areas. + + Telegram documentation: https://core.telegram.org/bots/api#storyareatypelink + + :param type: Type of the area, always “link” + :type type: :obj:`str` + + :param url: HTTP or tg:// URL to be opened when the area is clicked + :type url: :obj:`str` + + :return: Instance of the class + :rtype: :class:`StoryAreaTypeLink` + """ + def __init__(self, url: str, **kwargs): + self.type: str = "link" + self.url: str = url + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'type': self.type, + 'url': self.url + } + return data + +class StoryAreaTypeWeather(StoryAreaType): + """ + Describes a story area containing weather information. Currently, a story can have up to 3 weather areas. + + Telegram documentation: https://core.telegram.org/bots/api#storyareatypeweather + + :param type: Type of the area, always “weather” + :type type: :obj:`str` + + :param temperature: Temperature, in degree Celsius + :type temperature: :obj:`float` + + :param emoji: Emoji representing the weather + :type emoji: :obj:`str` + + :param background_color: A color of the area background in the ARGB format + :type background_color: :obj:`int` + + :return: Instance of the class + :rtype: :class:`StoryAreaTypeWeather` + """ + def __init__(self, temperature: float, emoji: str, background_color: int, **kwargs): + self.type: str = "weather" + self.temperature: float = temperature + self.emoji: str = emoji + self.background_color: int = background_color + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'type': self.type, + 'temperature': self.temperature, + 'emoji': self.emoji, + 'background_color': self.background_color + } + return data + +class StoryAreaTypeUniqueGift(StoryAreaType): + """ + Describes a story area pointing to a unique gift. Currently, a story can have at most 1 unique gift area. + + Telegram documentation: https://core.telegram.org/bots/api#storyareatypeuniquegift + + :param type: Type of the area, always “unique_gift” + :type type: :obj:`str` + + :param name: Unique name of the gift + :type name: :obj:`str` + + :return: Instance of the class + :rtype: :class:`StoryAreaTypeUniqueGift` + """ + def __init__(self, name: str, **kwargs): + self.type: str = "unique_gift" + self.name: str = name + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'type': self.type, + 'name': self.name + } + + return data + + +class StoryArea(JsonSerializable): + """ + Describes a clickable area on a story media. + + Telegram documentation: https://core.telegram.org/bots/api#storyarea + + :param position: Position of the area + :type position: :class:`StoryAreaPosition` + + :param type: Type of the area + :type type: :class:`StoryAreaType` + + :return: Instance of the class + :rtype: :class:`StoryArea` + """ + def __init__(self, position: StoryAreaPosition, type: StoryAreaType, **kwargs): + self.position: StoryAreaPosition = position + self.type: StoryAreaType = type + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'position': self.position.to_json(), + 'type': self.type.to_json() + } + return data + + + From 1c081633b5056ec4b7cc1cb733072e2da9636326 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 14:52:50 +0400 Subject: [PATCH 423/480] posting, editing, deleting stories(needs testing) --- telebot/__init__.py | 119 +++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 45 ++++++++++++++ telebot/async_telebot.py | 120 ++++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 45 ++++++++++++++ 4 files changed, 329 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 075d9f6e0..159d4b632 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6664,7 +6664,126 @@ def transfer_gift( new_owner_chat_id=new_owner_chat_id, star_count=star_count ) + + def post_story( + self, business_connection_id: str, content: types.InputStoryContent, + active_period: int, caption: Optional[str]=None, + parse_mode: Optional[str]=None, + caption_entities: Optional[List[types.MessageEntity]]=None, + areas: Optional[List[types.StoryArea]]=None, + post_to_chat_page: Optional[bool]=None, + protect_content: Optional[bool]=None) -> types.Story: + + """ + Posts a story on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns Story on success. + + Telegram documentation: https://core.telegram.org/bots/api#poststory + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param content: Content of the story + :type content: :class:`telebot.types.InputStoryContent` + + :param active_period: Period after which the story is moved to the archive, in seconds; must be one of 6 * 3600, 12 * 3600, 86400, or 2 * 86400 + :type active_period: :obj:`int` + + :param caption: Caption of the story, 0-2048 characters after entities parsing + :type caption: :obj:`str` + + :param parse_mode: Mode for parsing entities in the story caption. See formatting options for more details. + :type parse_mode: :obj:`str` + + :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :param areas: A JSON-serialized list of clickable areas to be shown on the story + :type areas: :obj:`list` of :class:`telebot.types.StoryArea` + + :param post_to_chat_page: Pass True to keep the story accessible after it expires + :type post_to_chat_page: :obj:`bool` + + :param protect_content: Pass True if the content of the story must be protected from forwarding and screenshotting + :type protect_content: :obj:`bool` + + :return: On success, a Story object is returned. + :rtype: :class:`telebot.types.Story` + """ + return types.Story.de_json( + apihelper.post_story( + self.token, business_connection_id, content, + active_period, caption=caption, + parse_mode=parse_mode, + caption_entities=caption_entities, + areas=areas, + post_to_chat_page=post_to_chat_page, + protect_content=protect_content + ) + ) + + def edit_story( + self, business_connection_id: str, story_id: int, + content: types.InputStoryContent, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, + caption_entities: Optional[List[types.MessageEntity]]=None, + areas: Optional[List[types.StoryArea]]=None) -> types.Story: + """ + Edits a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns Story on success. + Telegram documentation: https://core.telegram.org/bots/api#editstory + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param story_id: Unique identifier of the story to edit + :type story_id: :obj:`int` + + :param content: Content of the story + :type content: :class:`telebot.types.InputStoryContent` + + :param caption: Caption of the story, 0-2048 characters after entities parsing + :type caption: :obj:`str` + + :param parse_mode: Mode for parsing entities in the story caption. See formatting options for more details. + :type parse_mode: :obj:`str` + + :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :param areas: A JSON-serialized list of clickable areas to be shown on the story + :type areas: :obj:`list` of :class:`telebot.types.StoryArea` + + :return: On success, a Story object is returned. + :rtype: :class:`telebot.types.Story` + + """ + return types.Story.de_json( + apihelper.edit_story( + self.token, business_connection_id, story_id, + content, caption=caption, + parse_mode=parse_mode, + caption_entities=caption_entities, + areas=areas + ) + ) + + def delete_story(self, business_connection_id: str, story_id: int) -> bool: + """ + Deletes a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#deletestory + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param story_id: Unique identifier of the story to delete + :type story_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.delete_story(self.token, business_connection_id, story_id) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 366fb9435..d228023fb 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2090,6 +2090,51 @@ def transfer_gift(token, business_connection_id, owned_gift_id, new_owner_chat_i payload['star_count'] = star_count return _make_request(token, method_url, params=payload, method='post') +def post_story(token, business_connection_id, content, active_period, caption=None, parse_mode=None, + caption_entities=None, areas=None, post_to_chat_page=None, protect_content=None): + method_url = 'postStory' + payload = {'business_connection_id': business_connection_id, 'active_period': active_period} + + content_json, files = content.convert_input_story() + payload['content'] = content_json + + if caption: + payload['caption'] = caption + if parse_mode: + payload['parse_mode'] = parse_mode + if caption_entities: + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + if areas: + payload['areas'] = json.dumps([area.to_json() for area in areas]) + if post_to_chat_page is not None: + payload['post_to_chat_page'] = post_to_chat_page + if protect_content is not None: + payload['protect_content'] = protect_content + return _make_request(token, method_url, params=payload, files=files, method='post') + +def edit_story(token, business_connection_id, story_id, content, caption=None, parse_mode=None, + caption_entities=None, areas=None): + method_url = 'editStory' + payload = {'business_connection_id': business_connection_id, 'story_id': story_id} + + content_json, files = content.convert_input_story() + payload['content'] = content_json + + if caption: + payload['caption'] = caption + if parse_mode: + payload['parse_mode'] = parse_mode + if caption_entities: + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + if areas: + payload['areas'] = json.dumps([area.to_json() for area in areas]) + return _make_request(token, method_url, params=payload, files=files, method='post') + +def delete_story(token, business_connection_id, story_id): + method_url = 'deleteStory' + payload = {'business_connection_id': business_connection_id, 'story_id': story_id} + return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8c12e7891..ed6db2be3 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -8120,6 +8120,126 @@ async def transfer_gift( new_owner_chat_id=new_owner_chat_id, star_count=star_count ) + + async def post_story( + self, business_connection_id: str, content: types.InputStoryContent, + active_period: int, caption: Optional[str]=None, + parse_mode: Optional[str]=None, + caption_entities: Optional[List[types.MessageEntity]]=None, + areas: Optional[List[types.StoryArea]]=None, + post_to_chat_page: Optional[bool]=None, + protect_content: Optional[bool]=None) -> types.Story: + + """ + Posts a story on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns Story on success. + + Telegram documentation: https://core.telegram.org/bots/api#poststory + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param content: Content of the story + :type content: :class:`telebot.types.InputStoryContent` + + :param active_period: Period after which the story is moved to the archive, in seconds; must be one of 6 * 3600, 12 * 3600, 86400, or 2 * 86400 + :type active_period: :obj:`int` + + :param caption: Caption of the story, 0-2048 characters after entities parsing + :type caption: :obj:`str` + + :param parse_mode: Mode for parsing entities in the story caption. See formatting options for more details. + :type parse_mode: :obj:`str` + + :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :param areas: A JSON-serialized list of clickable areas to be shown on the story + :type areas: :obj:`list` of :class:`telebot.types.StoryArea` + + :param post_to_chat_page: Pass True to keep the story accessible after it expires + :type post_to_chat_page: :obj:`bool` + + :param protect_content: Pass True if the content of the story must be protected from forwarding and screenshotting + :type protect_content: :obj:`bool` + + :return: On success, a Story object is returned. + :rtype: :class:`telebot.types.Story` + """ + return types.Story.de_json( + await asyncio_helper.post_story( + self.token, business_connection_id, content, + active_period, caption=caption, + parse_mode=parse_mode, + caption_entities=caption_entities, + areas=areas, + post_to_chat_page=post_to_chat_page, + protect_content=protect_content + ) + ) + + async def edit_story( + self, business_connection_id: str, story_id: int, + content: types.InputStoryContent, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, + caption_entities: Optional[List[types.MessageEntity]]=None, + areas: Optional[List[types.StoryArea]]=None) -> types.Story: + """ + Edits a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns Story on success. + + Telegram documentation: https://core.telegram.org/bots/api#editstory + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param story_id: Unique identifier of the story to edit + :type story_id: :obj:`int` + + :param content: Content of the story + :type content: :class:`telebot.types.InputStoryContent` + + :param caption: Caption of the story, 0-2048 characters after entities parsing + :type caption: :obj:`str` + + :param parse_mode: Mode for parsing entities in the story caption. See formatting options for more details. + :type parse_mode: :obj:`str` + + :param caption_entities: A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode + :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :param areas: A JSON-serialized list of clickable areas to be shown on the story + :type areas: :obj:`list` of :class:`telebot.types.StoryArea` + + :return: On success, a Story object is returned. + :rtype: :class:`telebot.types.Story` + + """ + return types.Story.de_json( + await asyncio_helper.edit_story( + self.token, business_connection_id, story_id, + content, caption=caption, + parse_mode=parse_mode, + caption_entities=caption_entities, + areas=areas + ) + ) + + async def delete_story(self, business_connection_id: str, story_id: int) -> bool: + """ + Deletes a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#deletestory + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param story_id: Unique identifier of the story to delete + :type story_id: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.delete_story(self.token, business_connection_id, story_id) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index f539bd04e..9f1e26364 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2063,6 +2063,51 @@ async def transfer_gift(token, business_connection_id, owned_gift_id, new_owner_ payload['star_count'] = star_count return await _process_request(token, method_url, params=payload, method='post') +async def post_story(token, business_connection_id, content, active_period, caption=None, parse_mode=None, + caption_entities=None, areas=None, post_to_chat_page=None, protect_content=None): + method_url = 'postStory' + payload = {'business_connection_id': business_connection_id, 'active_period': active_period} + + content_json, files = content.convert_input_story() + payload['content'] = content_json + + if caption: + payload['caption'] = caption + if parse_mode: + payload['parse_mode'] = parse_mode + if caption_entities: + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + if areas: + payload['areas'] = json.dumps([area.to_json() for area in areas]) + if post_to_chat_page is not None: + payload['post_to_chat_page'] = post_to_chat_page + if protect_content is not None: + payload['protect_content'] = protect_content + return await _process_request(token, method_url, params=payload, files=files, method='post') + +async def edit_story(token, business_connection_id, story_id, content, caption=None, parse_mode=None, + caption_entities=None, areas=None): + method_url = 'editStory' + payload = {'business_connection_id': business_connection_id, 'story_id': story_id} + + content_json, files = content.convert_input_story() + payload['content'] = content_json + + if caption: + payload['caption'] = caption + if parse_mode: + payload['parse_mode'] = parse_mode + if caption_entities: + payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) + if areas: + payload['areas'] = json.dumps([area.to_json() for area in areas]) + return await _process_request(token, method_url, params=payload, files=files, method='post') + +async def delete_story(token, business_connection_id, story_id): + method_url = 'deleteStory' + payload = {'business_connection_id': business_connection_id, 'story_id': story_id} + return await _process_request(token, method_url, params=payload, method='post') + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) From b05d209900f31e4181be07ef9226b591ede4b408 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:33:14 +0400 Subject: [PATCH 424/480] Replaced the field can_send_gift with the field accepted_gift_types of the type AcceptedGiftTypes in the class ChatFullInfo. --- telebot/types.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 8745bfa66..4cd640819 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -691,6 +691,9 @@ class ChatFullInfo(JsonDeserializable): :param can_send_gift: Optional. True, if gifts can be sent to the chat :type can_send_gift: :obj:`bool` + :param accepted_gift_types: Information about types of gifts that are accepted by the chat or by the corresponding user for private chats + :type accepted_gift_types: :class:`telebot.types.AcceptedGiftTypes` + :param can_send_paid_media: Optional. True, if paid media messages can be sent or forwarded to the channel chat. The field is available only for channel chats. :type can_send_paid_media: :obj:`bool` @@ -762,6 +765,8 @@ def de_json(cls, json_string): obj['personal_chat'] = Chat.de_json(obj['personal_chat']) if 'birthdate' in obj: obj['birthdate'] = Birthdate.de_json(obj['birthdate']) + if 'accepted_gift_types' in obj: + obj['accepted_gift_types'] = AcceptedGiftTypes.de_json(obj['accepted_gift_types']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -777,7 +782,8 @@ def __init__(self, id, type, title=None, username=None, first_name=None, profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, business_opening_hours=None, personal_chat=None, birthdate=None, - can_send_paid_media=None, can_send_gift=None, **kwargs): + can_send_paid_media=None, + accepted_gift_types=None, **kwargs): self.id: int = id self.type: str = type self.title: Optional[str] = title @@ -822,7 +828,11 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.personal_chat: Optional[Chat] = personal_chat self.birthdate: Optional[Birthdate] = birthdate self.can_send_paid_media: Optional[bool] = can_send_paid_media - self.can_send_gift: Optional[bool] = can_send_gift + self.accepted_gift_types: AcceptedGiftTypes = accepted_gift_types + self.can_send_gift: Optional[bool] = None + if self.accepted_gift_types is not None: # not optional but still + # skip premium subscription? + self.can_send_gift: Optional[bool] = any([self.accepted_gift_types.unique_gifts, self.accepted_gift_types.unlimited_gifts, self.accepted_gift_types.limited_gifts]) class Chat(ChatFullInfo): From 6fedece26c4f26acd6fc50064e01cbe0a1e72641 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:38:56 +0400 Subject: [PATCH 425/480] Added unique_gift and gift --- telebot/types.py | 101 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 4cd640819..192bd7df8 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1124,6 +1124,12 @@ class Message(JsonDeserializable): :param chat_shared: Optional. Service message: a chat was shared with the bot :type chat_shared: :class:`telebot.types.ChatShared` + :param gift: Optional. Service message: a regular gift was sent or received + :type gift: :class:`telebot.types.GiftInfo` + + :param unique_gift: Optional. Service message: a unique gift was sent or received + :type unique_gift: :class:`telebot.types.UniqueGiftInfo` + :param connected_website: Optional. The domain name of the website on which the user has logged in. More about Telegram Login » :type connected_website: :obj:`str` @@ -1431,6 +1437,12 @@ def de_json(cls, json_string): opts['paid_media'] = PaidMediaInfo.de_json(obj['paid_media']) if 'refunded_payment' in obj: opts['refunded_payment'] = RefundedPayment.de_json(obj['refunded_payment']) + if 'gift' in obj: + opts['gift'] = GiftInfo.de_json(obj['gift']) + content_type = 'gift' + if 'unique_gift' in obj: + opts['unique_gift'] = UniqueGiftInfo.de_json(obj['unique_gift']) + content_type = 'unique_gift' return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1549,6 +1561,8 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.video_chat_participants_invited: Optional[VideoChatParticipantsInvited] = None self.web_app_data: Optional[WebAppData] = None self.message_auto_delete_timer_changed: Optional[MessageAutoDeleteTimerChanged] = None + self.gift : Optional[GiftInfo] = None + self.unique_gift : Optional[UniqueGiftInfo] = None for key in options: @@ -12180,4 +12194,91 @@ def to_dict(self): return data +class GiftInfo(JsonDeserializable): + """ + This object describes a service message about a regular gift that was sent or received. + + Telegram documentation: https://core.telegram.org/bots/api#giftinfo + + :param gift: Information about the gift + :type gift: :class:`Gift` + + :param owned_gift_id: Optional. Unique identifier of the received gift for the bot; only present for gifts received on behalf of business accounts + :type owned_gift_id: :obj:`str` + :param convert_star_count: Optional. Number of Telegram Stars that can be claimed by the receiver by converting the gift; omitted if conversion to Telegram Stars is impossible + :type convert_star_count: :obj:`int` + + :param prepaid_upgrade_star_count: Optional. Number of Telegram Stars that were prepaid by the sender for the ability to upgrade the gift + :type prepaid_upgrade_star_count: :obj:`int` + + :param can_be_upgraded: Optional. True, if the gift can be upgraded to a unique gift + :type can_be_upgraded: :obj:`bool` + + :param text: Optional. Text of the message that was added to the gift + :type text: :obj:`str` + + :param entities: Optional. Special entities that appear in the text + :type entities: :obj:`list` of :class:`MessageEntity` + + :param is_private: Optional. True, if the sender and gift text are shown only to the gift receiver; otherwise, everyone will be able to see them + :type is_private: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`GiftInfo` + """ + def __init__(self, gift: Gift, owned_gift_id: Optional[str] = None, convert_star_count: Optional[int] = None, + prepaid_upgrade_star_count: Optional[int] = None, can_be_upgraded: Optional[bool] = None, + text: Optional[str] = None, entities: Optional[List[MessageEntity]] = None, + is_private: Optional[bool] = None, **kwargs): + self.gift: Gift = gift + self.owned_gift_id: Optional[str] = owned_gift_id + self.convert_star_count: Optional[int] = convert_star_count + self.prepaid_upgrade_star_count: Optional[int] = prepaid_upgrade_star_count + self.can_be_upgraded: Optional[bool] = can_be_upgraded + self.text: Optional[str] = text + self.entities: Optional[List[MessageEntity]] = entities + self.is_private: Optional[bool] = is_private + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['gift'] = Gift.de_json(obj['gift']) + if 'entities' in obj: + obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] + return cls(**obj) + +class UniqueGiftInfo(JsonDeserializable): + """ + This object describes a service message about a unique gift that was sent or received. + + Telegram documentation: https://core.telegram.org/bots/api#uniquegiftinfo + + :param gift: Information about the gift + :type gift: :class:`UniqueGift` + + :param origin: Origin of the gift. Currently, either “upgrade” or “transfer” + :type origin: :obj:`str` + + :param owned_gift_id: Optional. Unique identifier of the received gift for the bot; only present for gifts received on behalf of business accounts + :type owned_gift_id: :obj:`str` + + :param transfer_star_count: Optional. Number of Telegram Stars that must be paid to transfer the gift; omitted if the bot cannot transfer the gift + :type transfer_star_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`UniqueGiftInfo` + """ + def __init__(self, gift: UniqueGift, origin: str, owned_gift_id: Optional[str] = None, + transfer_star_count: Optional[int] = None, **kwargs): + self.gift: UniqueGift = gift + self.origin: str = origin + self.owned_gift_id: Optional[str] = owned_gift_id + self.transfer_star_count: Optional[int] = transfer_star_count + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + obj['gift'] = UniqueGift.de_json(obj['gift']) + return cls(**obj) + \ No newline at end of file From e3d7f9640fbbfa8ba71531aae3055aee355023c7 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:41:45 +0400 Subject: [PATCH 426/480] Added gift_premium_subscription --- telebot/__init__.py | 36 ++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 12 ++++++++++++ telebot/async_telebot.py | 36 ++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 13 +++++++++++++ 4 files changed, 97 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index 159d4b632..9063bb48e 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6785,6 +6785,42 @@ def delete_story(self, business_connection_id: str, story_id: int) -> bool: """ return apihelper.delete_story(self.token, business_connection_id, story_id) + def gift_premium_subscription( + self, user_id: int, month_count: int, star_count: int, + text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + """ + Gifts a Telegram Premium subscription to the given user. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#giftpremiumsubscription + + :param user_id: Unique identifier of the target user who will receive a Telegram Premium subscription + :type user_id: :obj:`int` + + :param month_count: Number of months the Telegram Premium subscription will be active for the user; must be one of 3, 6, or 12 + :type month_count: :obj:`int` + + :param star_count: Number of Telegram Stars to pay for the Telegram Premium subscription; must be 1000 for 3 months, 1500 for 6 months, and 2500 for 12 months + :type star_count: :obj:`int` + + :param text: Text that will be shown along with the service message about the subscription; 0-128 characters + :type text: :obj:`str` + + :param text_parse_mode: Mode for parsing entities in the text. See formatting options for more details. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_parse_mode: :obj:`str` + + :param text_entities: A JSON-serialized list of special entities that appear in the gift text. It can be specified instead of text_parse_mode. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.gift_premium_subscription( + self.token, user_id, month_count, star_count, + text=text, text_parse_mode=text_parse_mode, + text_entities=text_entities + ) + def get_available_gifts(self) -> types.Gifts: """ Returns the list of gifts that can be sent by the bot to users. Requires no parameters. Returns a Gifts object. diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d228023fb..486aea481 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2135,6 +2135,18 @@ def delete_story(token, business_connection_id, story_id): payload = {'business_connection_id': business_connection_id, 'story_id': story_id} return _make_request(token, method_url, params=payload, method='post') +def gift_premium_subscription(token, user_id, month_count, star_count, text=None, text_parse_mode=None, + text_entities=None): + method_url = 'giftPremiumSubscription' + payload = {'user_id': user_id, 'month_count': month_count, 'star_count': star_count} + if text: + payload['text'] = text + if text_parse_mode: + payload['text_parse_mode'] = text_parse_mode + if text_entities: + payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index ed6db2be3..0c81b9c99 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -8240,6 +8240,42 @@ async def delete_story(self, business_connection_id: str, story_id: int) -> bool :rtype: :obj:`bool` """ return await asyncio_helper.delete_story(self.token, business_connection_id, story_id) + + async def gift_premium_subscription( + self, user_id: int, month_count: int, star_count: int, + text: Optional[str]=None, text_parse_mode: Optional[str]=None, + text_entities: Optional[List[types.MessageEntity]]=None) -> bool: + """ + Gifts a Telegram Premium subscription to the given user. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#giftpremiumsubscription + + :param user_id: Unique identifier of the target user who will receive a Telegram Premium subscription + :type user_id: :obj:`int` + + :param month_count: Number of months the Telegram Premium subscription will be active for the user; must be one of 3, 6, or 12 + :type month_count: :obj:`int` + + :param star_count: Number of Telegram Stars to pay for the Telegram Premium subscription; must be 1000 for 3 months, 1500 for 6 months, and 2500 for 12 months + :type star_count: :obj:`int` + + :param text: Text that will be shown along with the service message about the subscription; 0-128 characters + :type text: :obj:`str` + + :param text_parse_mode: Mode for parsing entities in the text. See formatting options for more details. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_parse_mode: :obj:`str` + + :param text_entities: A JSON-serialized list of special entities that appear in the gift text. It can be specified instead of text_parse_mode. Entities other than “bold”, “italic”, “underline”, “strikethrough”, “spoiler”, and “custom_emoji” are ignored. + :type text_entities: :obj:`list` of :class:`telebot.types.MessageEntity` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.gift_premium_subscription( + self.token, user_id, month_count, star_count, + text=text, text_parse_mode=text_parse_mode, + text_entities=text_entities + ) async def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 9f1e26364..1969b72f8 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2108,6 +2108,19 @@ async def delete_story(token, business_connection_id, story_id): payload = {'business_connection_id': business_connection_id, 'story_id': story_id} return await _process_request(token, method_url, params=payload, method='post') +async def gift_premium_subscription(token, user_id, month_count, star_count, text=None, text_parse_mode=None, + text_entities=None): + method_url = 'giftPremiumSubscription' + payload = {'user_id': user_id, 'month_count': month_count, 'star_count': star_count} + if text: + payload['text'] = text + if text_parse_mode: + payload['text_parse_mode'] = text_parse_mode + if text_entities: + payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) + return await _process_request(token, method_url, params=payload, method='post') + + async def get_available_gifts(token): method_url = 'getAvailableGifts' return await _process_request(token, method_url) From f76cac835a2fb99e54212c828d8deb7a5ad96838 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:43:38 +0400 Subject: [PATCH 427/480] Added premium_subscription_duration to TransactionPartnerUser --- telebot/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 192bd7df8..98fea4423 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10569,12 +10569,15 @@ class TransactionPartnerUser(TransactionPartner): :param gift: Optional. The gift sent to the user by the bot :type gift: :class:`Gift` + :param premium_subscription_duration: Optional. Number of months the gifted Telegram Premium subscription will be active for; for “premium_purchase” transactions only + :type premium_subscription_duration: :obj:`int` + :return: Instance of the class :rtype: :class:`TransactionPartnerUser` """ def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, - subscription_period=None, gift: Optional[Gift] = None, **kwargs): + subscription_period=None, gift: Optional[Gift] = None, premium_subscription_duration: Optional[int] = None, **kwargs): self.type: str = type self.user: User = user self.affiliate: Optional[AffiliateInfo] = affiliate @@ -10582,6 +10585,7 @@ def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: self.paid_media: Optional[List[PaidMedia]] = paid_media self.subscription_period: Optional[int] = subscription_period self.gift: Optional[Gift] = gift + self.premium_subscription_duration: Optional[int] = premium_subscription_duration @classmethod def de_json(cls, json_string): From 0bd9133cc3f83b1b60f7db535fabc7a8637dcbae Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:45:12 +0400 Subject: [PATCH 428/480] Added transaction_type to TransactionPartnerUser --- telebot/types.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 98fea4423..7435a680e 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -10551,6 +10551,11 @@ class TransactionPartnerUser(TransactionPartner): :param type: Type of the transaction partner, always “user” :type type: :obj:`str` + :param transaction_type: Type of the transaction, currently one of “invoice_payment” for payments via invoices, + “paid_media_payment” for payments for paid media, “gift_purchase” for gifts sent by the bot, “premium_purchase” for Telegram Premium subscriptions + gifted by the bot, “business_account_transfer” for direct transfers from managed business accounts + :type transaction_type: :obj:`str` + :param user: Information about the user :type user: :class:`User` @@ -10577,7 +10582,8 @@ class TransactionPartnerUser(TransactionPartner): """ def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, - subscription_period=None, gift: Optional[Gift] = None, premium_subscription_duration: Optional[int] = None, **kwargs): + subscription_period=None, gift: Optional[Gift] = None, premium_subscription_duration: Optional[int] = None, + transaction_type: Optional[str] = None, **kwargs): self.type: str = type self.user: User = user self.affiliate: Optional[AffiliateInfo] = affiliate @@ -10586,6 +10592,7 @@ def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: self.subscription_period: Optional[int] = subscription_period self.gift: Optional[Gift] = gift self.premium_subscription_duration: Optional[int] = premium_subscription_duration + self.transaction_type: Optional[str] = transaction_type @classmethod def de_json(cls, json_string): From 950d7c6da012cfee67db1c3651573d8e03b2340c Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:50:21 +0400 Subject: [PATCH 429/480] Added paid_message_price_changed --- telebot/types.py | 28 ++++++++++++++++++++++++++++ telebot/version.py | 3 --- 2 files changed, 28 insertions(+), 3 deletions(-) delete mode 100644 telebot/version.py diff --git a/telebot/types.py b/telebot/types.py index 7435a680e..6c681ba2b 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1181,6 +1181,9 @@ class Message(JsonDeserializable): :param giveaway_completed: Optional. Service message: giveaway completed, without public winners :type giveaway_completed: :class:`telebot.types.GiveawayCompleted` + :param paid_message_price_changed: Optional. Service message: the price for paid messages has changed in the chat + :type paid_message_price_changed: :class:`telebot.types.PaidMessagePriceChanged` + :param video_chat_scheduled: Optional. Service message: video chat scheduled :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` @@ -1443,6 +1446,9 @@ def de_json(cls, json_string): if 'unique_gift' in obj: opts['unique_gift'] = UniqueGiftInfo.de_json(obj['unique_gift']) content_type = 'unique_gift' + if 'paid_message_price_changed' in obj: + opts['paid_message_price_changed'] = PaidMessagePriceChanged.de_json(obj['paid_message_price_changed']) + content_type = 'paid_message_price_changed' return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1563,6 +1569,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.message_auto_delete_timer_changed: Optional[MessageAutoDeleteTimerChanged] = None self.gift : Optional[GiftInfo] = None self.unique_gift : Optional[UniqueGiftInfo] = None + self.paid_message_price_changed: Optional[PaidMessagePriceChanged] = None for key in options: @@ -12292,4 +12299,25 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['gift'] = UniqueGift.de_json(obj['gift']) return cls(**obj) + + +class PaidMessagePriceChanged(JsonDeserializable): + """ + Describes a service message about a change in the price of paid messages within a chat. + + Telegram documentation: https://core.telegram.org/bots/api#paidmessagepricechanged + + :param paid_message_star_count: The new number of Telegram Stars that must be paid by non-administrator users of the supergroup chat for each sent message + :type paid_message_star_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`PaidMessagePriceChanged` + """ + def __init__(self, paid_message_star_count: int, **kwargs): + self.paid_message_star_count: int = paid_message_star_count + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) \ No newline at end of file diff --git a/telebot/version.py b/telebot/version.py deleted file mode 100644 index b37f3e662..000000000 --- a/telebot/version.py +++ /dev/null @@ -1,3 +0,0 @@ -# Versions should comply with PEP440. -# This line is parsed in setup.py: -__version__ = '4.26.0' From 9fb4fdd78ba954aca732f90fa6f74969f3a3811a Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 22:52:55 +0400 Subject: [PATCH 430/480] Added paid_star_count --- telebot/types.py | 7 +++++++ telebot/version.py | 3 +++ 2 files changed, 10 insertions(+) create mode 100644 telebot/version.py diff --git a/telebot/types.py b/telebot/types.py index 6c681ba2b..33aff6822 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -981,6 +981,9 @@ class Message(JsonDeserializable): anonymous group administrator :type author_signature: :obj:`str` + :param paid_star_count: Optional. The number of Telegram Stars that were paid by the sender of the message to send it + :type paid_star_count: :obj:`int` + :param text: Optional. For text messages, the actual UTF-8 text of the message :type text: :obj:`str` @@ -1449,6 +1452,9 @@ def de_json(cls, json_string): if 'paid_message_price_changed' in obj: opts['paid_message_price_changed'] = PaidMessagePriceChanged.de_json(obj['paid_message_price_changed']) content_type = 'paid_message_price_changed' + if 'paid_star_count' in obj: + opts['paid_star_count'] = obj['paid_star_count'] + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1570,6 +1576,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.gift : Optional[GiftInfo] = None self.unique_gift : Optional[UniqueGiftInfo] = None self.paid_message_price_changed: Optional[PaidMessagePriceChanged] = None + self.paid_star_count: Optional[int] = None for key in options: diff --git a/telebot/version.py b/telebot/version.py new file mode 100644 index 000000000..b37f3e662 --- /dev/null +++ b/telebot/version.py @@ -0,0 +1,3 @@ +# Versions should comply with PEP440. +# This line is parsed in setup.py: +__version__ = '4.26.0' From 0d1e51519c012fcb5f8cc6899f01a1e01fe914fa Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 12 Apr 2025 23:01:31 +0400 Subject: [PATCH 431/480] Added set_business_account_profile_photo and remove_business_account_profile_photo --- telebot/__init__.py | 42 +++++++++++++++++++ telebot/apihelper.py | 16 +++++++ telebot/async_telebot.py | 42 +++++++++++++++++++ telebot/asyncio_helper.py | 16 +++++++ telebot/types.py | 87 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 202 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 9063bb48e..28f479a3b 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6820,6 +6820,48 @@ def gift_premium_subscription( text=text, text_parse_mode=text_parse_mode, text_entities=text_entities ) + + def set_business_account_profile_photo( + self, business_connection_id: str, photo: types.InputProfilePhoto, + is_public: Optional[bool]=None) -> bool: + """ + Changes the profile photo of a managed business account. Requires the can_edit_profile_photo business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountprofilephoto + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param photo: The new profile photo to set + :type photo: :class:`telebot.types.InputProfilePhoto` + + :param is_public: Pass True to set the public photo, which will be visible even if the main photo is hidden by the business account's privacy settings. An account can have only one public photo. + :type is_public: :obj:`bool` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.set_business_account_profile_photo(self.token, business_connection_id, photo, is_public=is_public) + + + def remove_business_account_profile_photo( + self, business_connection_id: str, + is_public: Optional[bool]=None) -> bool: + """ + Removes the current profile photo of a managed business account. Requires the can_edit_profile_photo business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removebusinessaccountprofilephoto + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param is_public: Pass True to remove the public photo, which is visible even if the main photo is hidden by the business account's privacy settings. After the main photo is removed, the previous profile photo (if present) becomes the main photo. + :type is_public: :obj:`bool` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.remove_business_account_profile_photo(self.token, business_connection_id, is_public=is_public) def get_available_gifts(self) -> types.Gifts: """ diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 486aea481..d4aba417f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2147,6 +2147,22 @@ def gift_premium_subscription(token, user_id, month_count, star_count, text=None payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) return _make_request(token, method_url, params=payload, method='post') +def set_business_account_profile_photo(token, business_connection_id, photo, is_public=None): + method_url = 'setBusinessAccountProfilePhoto' + payload = {'business_connection_id': business_connection_id} + photo_json, files = photo.convert_input_profile_photo() + payload['photo'] = photo_json + if is_public is not None: + payload['is_public'] = is_public + return _make_request(token, method_url, params=payload, files=files, method='post') + +def remove_business_account_profile_photo(token, business_connection_id, is_public=None): + method_url = 'removeBusinessAccountProfilePhoto' + payload = {'business_connection_id': business_connection_id} + if is_public is not None: + payload['is_public'] = is_public + return _make_request(token, method_url, params=payload, method='post') + def create_new_sticker_set( token, user_id, name, title, stickers, sticker_type=None, needs_repainting=None): method_url = 'createNewStickerSet' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 0c81b9c99..1eaa8271e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -8241,6 +8241,48 @@ async def delete_story(self, business_connection_id: str, story_id: int) -> bool """ return await asyncio_helper.delete_story(self.token, business_connection_id, story_id) + async def set_business_account_profile_photo( + self, business_connection_id: str, photo: types.InputProfilePhoto, + is_public: Optional[bool]=None) -> bool: + """ + Changes the profile photo of a managed business account. Requires the can_edit_profile_photo business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#setbusinessaccountprofilephoto + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param photo: The new profile photo to set + :type photo: :class:`telebot.types.InputProfilePhoto` + + :param is_public: Pass True to set the public photo, which will be visible even if the main photo is hidden by the business account's privacy settings. An account can have only one public photo. + :type is_public: :obj:`bool` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.set_business_account_profile_photo(self.token, business_connection_id, photo, is_public=is_public) + + + async def remove_business_account_profile_photo( + self, business_connection_id: str, + is_public: Optional[bool]=None) -> bool: + """ + Removes the current profile photo of a managed business account. Requires the can_edit_profile_photo business bot right. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#removebusinessaccountprofilephoto + + :param business_connection_id: Unique identifier of the business connection + :type business_connection_id: :obj:`str` + + :param is_public: Pass True to remove the public photo, which is visible even if the main photo is hidden by the business account's privacy settings. After the main photo is removed, the previous profile photo (if present) becomes the main photo. + :type is_public: :obj:`bool` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.remove_business_account_profile_photo(self.token, business_connection_id, is_public=is_public) + async def gift_premium_subscription( self, user_id: int, month_count: int, star_count: int, text: Optional[str]=None, text_parse_mode: Optional[str]=None, diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 1969b72f8..14203900d 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2120,6 +2120,22 @@ async def gift_premium_subscription(token, user_id, month_count, star_count, tex payload['text_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(text_entities)) return await _process_request(token, method_url, params=payload, method='post') +async def set_business_account_profile_photo(token, business_connection_id, photo, is_public=None): + method_url = 'setBusinessAccountProfilePhoto' + payload = {'business_connection_id': business_connection_id} + photo_json, files = photo.convert_input_profile_photo() + payload['photo'] = photo_json + if is_public is not None: + payload['is_public'] = is_public + return await _process_request(token, method_url, params=payload, files=files, method='post') + +async def remove_business_account_profile_photo(token, business_connection_id, is_public=None): + method_url = 'removeBusinessAccountProfilePhoto' + payload = {'business_connection_id': business_connection_id} + if is_public is not None: + payload['is_public'] = is_public + return await _process_request(token, method_url, params=payload, method='post') + async def get_available_gifts(token): method_url = 'getAvailableGifts' diff --git a/telebot/types.py b/telebot/types.py index 33aff6822..a97c60c34 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -12327,4 +12327,89 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - \ No newline at end of file + + +class InputProfilePhoto(JsonSerializable): + """ + This object describes a profile photo to set. Currently, it can be one of + InputProfilePhotoStatic + InputProfilePhotoAnimated + + Telegram documentation: https://core.telegram.org/bots/api#inputprofilephoto + + :return: Instance of the class + :rtype: :class:`InputProfilePhoto` + """ + +class InputProfilePhotoStatic(InputProfilePhoto): + """ + This object describes a static profile photo to set. + + Telegram documentation: https://core.telegram.org/bots/api#inputprofilephotostatic + + :param type: Type of the profile photo, must be static + :type type: :obj:`str` + + :param photo: The static profile photo. Profile photos can't be reused and can only be uploaded as a new file, so you can pass “attach://” if the photo was uploaded using multipart/form-data under . More information on Sending Files + :type photo: :obj:`str` + + :return: Instance of the class + :rtype: :class:`InputProfilePhotoStatic` + + """ + def __init__(self, photo: InputFile, **kwargs): + self.type: str = "static" + self.photo: InputFile = photo + + self._photo_name = service_utils.generate_random_token() + self._photo_dic = "attach://{}".format(self._photo_name) + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'type': self.type, + 'photo': self._photo_dic + } + return data + def convert_input_profile_photo(self): + return self.to_json(), {self._photo_name: self.photo} + + +class InputProfilePhotoAnimated(InputProfilePhoto): + """ + This object describes an animated profile photo to set. + + Telegram documentation: https://core.telegram.org/bots/api#inputprofilephotoanimated + + :param type: Type of the profile photo, must be animated + :type type: :obj:`str` + + :param animation: The animated profile photo. Profile photos can't be reused and can only be uploaded as a new file, so you can pass “attach://” if the photo was uploaded using multipart/form-data under . More information on Sending Files + :type animation: :obj:`str` + + :param main_frame_timestamp: Optional. Timestamp in seconds of the frame that will be used as the static profile photo. Defaults to 0.0. + :type main_frame_timestamp: :obj:`float` + + :return: Instance of the class + :rtype: :class:`InputProfilePhotoAnimated` + + """ + def __init__(self, animation: InputFile, main_frame_timestamp: Optional[float] = None, **kwargs): + self.type: str = "animated" + self.animation: InputFile = animation + self._animation_name = service_utils.generate_random_token() + self._animation_dic = "attach://{}".format(self._animation_name) + self.main_frame_timestamp: Optional[float] = main_frame_timestamp + def to_json(self): + return json.dumps(self.to_dict()) + def to_dict(self): + data = { + 'type': self.type, + 'animation': self._animation_dic + } + if self.main_frame_timestamp is not None: + data['main_frame_timestamp'] = self.main_frame_timestamp + return data + def convert_input_profile_photo(self): + return self.to_json(), {self._animation_name: self.animation} From d63b07af0bd03ccafca188559bfdb1204dcd3513 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 13 Apr 2025 20:09:44 +0400 Subject: [PATCH 432/480] Fix issues with posting stories --- telebot/apihelper.py | 4 ++-- telebot/types.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d4aba417f..0e2ce593e 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2105,7 +2105,7 @@ def post_story(token, business_connection_id, content, active_period, caption=No if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if areas: - payload['areas'] = json.dumps([area.to_json() for area in areas]) + payload['areas'] = json.dumps([area.to_dict() for area in areas]) if post_to_chat_page is not None: payload['post_to_chat_page'] = post_to_chat_page if protect_content is not None: @@ -2127,7 +2127,7 @@ def edit_story(token, business_connection_id, story_id, content, caption=None, p if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if areas: - payload['areas'] = json.dumps([area.to_json() for area in areas]) + payload['areas'] = json.dumps([area.to_dict() for area in areas]) return _make_request(token, method_url, params=payload, files=files, method='post') def delete_story(token, business_connection_id, story_id): diff --git a/telebot/types.py b/telebot/types.py index a97c60c34..2939c9e5f 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -12054,7 +12054,7 @@ def to_dict(self): 'type': self.type, 'latitude': self.latitude, 'longitude': self.longitude, - 'address': self.address.to_json() + 'address': self.address.to_dict() } return data @@ -12090,7 +12090,7 @@ def to_json(self): def to_dict(self): data = { 'type': self.type, - 'reaction_type': self.reaction_type.to_json() + 'reaction_type': self.reaction_type.to_dict() } if self.is_dark is not None: data['is_dark'] = self.is_dark @@ -12213,8 +12213,8 @@ def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): data = { - 'position': self.position.to_json(), - 'type': self.type.to_json() + 'position': self.position.to_dict(), + 'type': self.type.to_dict() } return data From 49684b5f9ca4391426c95bf22228c1cc3882f028 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 13 Apr 2025 20:15:50 +0400 Subject: [PATCH 433/480] Fix stories for async --- telebot/asyncio_helper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 14203900d..67990da54 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -2078,7 +2078,7 @@ async def post_story(token, business_connection_id, content, active_period, capt if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if areas: - payload['areas'] = json.dumps([area.to_json() for area in areas]) + payload['areas'] = json.dumps([area.to_dict() for area in areas]) if post_to_chat_page is not None: payload['post_to_chat_page'] = post_to_chat_page if protect_content is not None: @@ -2100,7 +2100,7 @@ async def edit_story(token, business_connection_id, story_id, content, caption=N if caption_entities: payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities)) if areas: - payload['areas'] = json.dumps([area.to_json() for area in areas]) + payload['areas'] = json.dumps([area.to_dict() for area in areas]) return await _process_request(token, method_url, params=payload, files=files, method='post') async def delete_story(token, business_connection_id, story_id): From 7007eca960ca5f463d59e32e39096ff90b32e806 Mon Sep 17 00:00:00 2001 From: "g.zinovev" Date: Mon, 14 Apr 2025 01:02:31 +0300 Subject: [PATCH 434/480] Fix: Add thumbnail support for edit_message_media --- telebot/types.py | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index af0d4cf74..2cd6b8066 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6695,12 +6695,20 @@ class InputMedia(Dictionaryable, JsonSerializable): * :class:`InputMediaPhoto` * :class:`InputMediaVideo` """ - def __init__(self, type, media, caption=None, parse_mode=None, caption_entities=None): + def __init__(self, type, media, caption=None, parse_mode=None, caption_entities=None, thumbnail=None): self.type: str = type self.media: str = media self.caption: Optional[str] = caption self.parse_mode: Optional[str] = parse_mode self.caption_entities: Optional[List[MessageEntity]] = caption_entities + self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + + if isinstance(self.thumbnail, InputFile): + self._thumbnail_name = service_utils.generate_random_token() + self._thumbnail_dic = 'attach://{0}'.format(self._thumbnail_name) + else: + self._thumbnail_name = '' + self._thumbnail_dic = self.thumbnail if service_utils.is_string(self.media): self._media_name = '' @@ -6713,7 +6721,7 @@ def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): - json_dict = {'type': self.type, 'media': self._media_dic} + json_dict = {'type': self.type, 'media': self._media_dic, 'thumbnail': self._thumbnail_dic} if self.caption: json_dict['caption'] = self.caption if self.parse_mode: @@ -6729,7 +6737,7 @@ def convert_input_media(self): if service_utils.is_string(self.media): return self.to_json(), None - return self.to_json(), {self._media_name: self.media} + return self.to_json(), {self._media_name: self.media, self._thumbnail_name: self.thumbnail} class InputMediaPhoto(InputMedia): @@ -6850,8 +6858,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, show_caption_above_media: Optional[bool] = None, cover: Optional[Union[str, InputFile]] = None, start_timestamp: Optional[int] = None): super(InputMediaVideo, self).__init__( - type="video", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + type="video", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, thumbnail=thumbnail) self.width: Optional[int] = width self.height: Optional[int] = height self.duration: Optional[int] = duration @@ -6868,8 +6875,6 @@ def thumb(self) -> Optional[Union[str, Any]]: def to_dict(self): ret = super(InputMediaVideo, self).to_dict() - if self.thumbnail: - ret['thumbnail'] = self.thumbnail if self.width: ret['width'] = self.width if self.height: @@ -6943,8 +6948,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, height: Optional[int] = None, duration: Optional[int] = None, has_spoiler: Optional[bool] = None, show_caption_above_media: Optional[bool] = None): super(InputMediaAnimation, self).__init__( - type="animation", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + type="animation", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, thumbnail=thumbnail) self.width: Optional[int] = width self.height: Optional[int] = height self.duration: Optional[int] = duration @@ -6959,8 +6963,6 @@ def thumb(self) -> Optional[Union[str, Any]]: def to_dict(self): ret = super(InputMediaAnimation, self).to_dict() - if self.thumbnail: - ret['thumbnail'] = self.thumbnail if self.width: ret['width'] = self.width if self.height: @@ -7020,8 +7022,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, caption_entities: Optional[List[MessageEntity]] = None, duration: Optional[int] = None, performer: Optional[str] = None, title: Optional[str] = None): super(InputMediaAudio, self).__init__( - type="audio", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + type="audio", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, thumbnail=thumbnail) self.duration: Optional[int] = duration self.performer: Optional[str] = performer self.title: Optional[str] = title @@ -7033,8 +7034,6 @@ def thumb(self) -> Optional[Union[str, Any]]: def to_dict(self): ret = super(InputMediaAudio, self).to_dict() - if self.thumbnail: - ret['thumbnail'] = self.thumbnail if self.duration: ret['duration'] = self.duration if self.performer: @@ -7085,8 +7084,7 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[Union[str, caption_entities: Optional[List[MessageEntity]] = None, disable_content_type_detection: Optional[bool] = None): super(InputMediaDocument, self).__init__( - type="document", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) - self.thumbnail: Optional[Union[str, InputFile]] = thumbnail + type="document", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities, thumbnail=thumbnail) self.disable_content_type_detection: Optional[bool] = disable_content_type_detection @property @@ -7096,8 +7094,6 @@ def thumb(self) -> Optional[Union[str, Any]]: def to_dict(self): ret = super(InputMediaDocument, self).to_dict() - if self.thumbnail: - ret['thumbnail'] = self.thumbnail if self.disable_content_type_detection is not None: ret['disable_content_type_detection'] = self.disable_content_type_detection return ret From 533b52c79376a9143d09a090a329f6d07835f199 Mon Sep 17 00:00:00 2001 From: _run Date: Sat, 19 Apr 2025 21:13:36 +0400 Subject: [PATCH 435/480] Fix issues related with Bot api 9.0 --- telebot/__init__.py | 14 +++--- telebot/apihelper.py | 15 ++++-- telebot/async_telebot.py | 14 +++--- telebot/asyncio_helper.py | 14 ++++-- telebot/types.py | 96 +++++++++++++++++++++++---------------- 5 files changed, 91 insertions(+), 62 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 28f479a3b..5a3064c48 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -6364,7 +6364,7 @@ def remove_user_verification(self, user_id: int) -> bool: return apihelper.remove_user_verification(self.token, user_id) - def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: + def remove_chat_verification(self, chat_id: int) -> bool: """ Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. Returns True on success. @@ -6433,7 +6433,7 @@ def set_business_account_name(self, business_connection_id: str, first_name: str :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.set_business_account_name(self.token, business_connection_id, first_name, last_name) + return apihelper.set_business_account_name(self.token, business_connection_id, first_name, last_name=last_name) def set_business_account_username(self, business_connection_id: str, username: Optional[str]=None) -> bool: """ @@ -6451,7 +6451,7 @@ def set_business_account_username(self, business_connection_id: str, username: O :rtype: :obj:`bool` """ - return apihelper.set_business_account_username(self.token, business_connection_id, username) + return apihelper.set_business_account_username(self.token, business_connection_id, username=username) def set_business_account_bio(self, business_connection_id: str, bio: Optional[str]=None) -> bool: """ @@ -6468,7 +6468,7 @@ def set_business_account_bio(self, business_connection_id: str, bio: Optional[st :return: Returns True on success. :rtype: :obj:`bool` """ - return apihelper.set_business_account_bio(self.token, business_connection_id, bio) + return apihelper.set_business_account_bio(self.token, business_connection_id, bio=bio) def set_business_account_gift_settings( self, business_connection_id: str, show_gift_button: bool, accepted_gift_types: types.AcceptedGiftTypes) -> bool: @@ -6635,7 +6635,7 @@ def upgrade_gift( def transfer_gift( self, business_connection_id: str, owned_gift_id: str, - new_owner_chat_id: Union[int, str], + new_owner_chat_id: int, star_count: Optional[int]=None) -> bool: """ Transfers an owned unique gift to another user. Requires the can_transfer_and_upgrade_gifts business bot right. @@ -6650,7 +6650,7 @@ def transfer_gift( :type owned_gift_id: :obj:`str` :param new_owner_chat_id: Unique identifier of the chat which will own the gift. The chat must be active in the last 24 hours. - :type new_owner_chat_id: :obj:`int` | :obj:`str` + :type new_owner_chat_id: :obj:`int` :param star_count: The amount of Telegram Stars that will be paid for the transfer from the business account balance. If positive, then the can_transfer_stars business bot right is required. @@ -6661,7 +6661,7 @@ def transfer_gift( """ return apihelper.transfer_gift( self.token, business_connection_id, owned_gift_id, - new_owner_chat_id=new_owner_chat_id, + new_owner_chat_id, star_count=star_count ) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 0e2ce593e..460c3c4a6 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -2013,21 +2013,26 @@ def set_business_account_name(token, business_connection_id, first_name, last_na return _make_request(token, method_url, params=payload, method='post') -def set_business_account_username(token, business_connection_id, username): +def set_business_account_username(token, business_connection_id, username=None): method_url = 'setBusinessAccountUsername' - payload = {'business_connection_id': business_connection_id, 'username': username} + payload = {'business_connection_id': business_connection_id} + if username: + payload['username'] = username return _make_request(token, method_url, params=payload, method='post') -def set_business_account_bio(token, business_connection_id, bio): +def set_business_account_bio(token, business_connection_id, bio=None): method_url = 'setBusinessAccountBio' - payload = {'business_connection_id': business_connection_id, 'bio': bio} + payload = {'business_connection_id': business_connection_id} + if bio: + payload['bio'] = bio return _make_request(token, method_url, params=payload, method='post') def set_business_account_gift_settings(token, business_connection_id, show_gift_button, accepted_gift_types): method_url = 'setBusinessAccountGiftSettings' - payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, 'accepted_gift_types': json.dumps(accepted_gift_types)} + payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, + 'accepted_gift_types': accepted_gift_types.to_json()} return _make_request(token, method_url, params=payload, method='post') def set_sticker_emoji_list(token, sticker, emoji_list): diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 1eaa8271e..26e34934b 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -7821,7 +7821,7 @@ async def remove_user_verification(self, user_id: int) -> bool: """ return await asyncio_helper.remove_user_verification(self.token, user_id) - async def remove_chat_verification(self, chat_id: Union[int, str]) -> bool: + async def remove_chat_verification(self, chat_id: int) -> bool: """ Removes verification from a chat that is currently verified on behalf of the organization represented by the bot. Returns True on success. @@ -7890,7 +7890,7 @@ async def set_business_account_name(self, business_connection_id: str, first_nam :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.set_business_account_name(self.token, business_connection_id, first_name, last_name) + return await asyncio_helper.set_business_account_name(self.token, business_connection_id, first_name, last_name=last_name) async def set_business_account_username(self, business_connection_id: str, username: Optional[str]=None) -> bool: """ @@ -7908,7 +7908,7 @@ async def set_business_account_username(self, business_connection_id: str, usern :rtype: :obj:`bool` """ - return await asyncio_helper.set_business_account_username(self.token, business_connection_id, username) + return await asyncio_helper.set_business_account_username(self.token, business_connection_id, username=username) async def set_business_account_bio(self, business_connection_id: str, bio: Optional[str]=None) -> bool: """ @@ -7925,7 +7925,7 @@ async def set_business_account_bio(self, business_connection_id: str, bio: Optio :return: Returns True on success. :rtype: :obj:`bool` """ - return await asyncio_helper.set_business_account_bio(self.token, business_connection_id, bio) + return await asyncio_helper.set_business_account_bio(self.token, business_connection_id, bio=bio) async def set_business_account_gift_settings( self, business_connection_id: str, show_gift_button: bool, accepted_gift_types: types.AcceptedGiftTypes) -> bool: @@ -8091,7 +8091,7 @@ async def upgrade_gift( async def transfer_gift( self, business_connection_id: str, owned_gift_id: str, - new_owner_chat_id: Union[int, str], + new_owner_chat_id: int, star_count: Optional[int]=None) -> bool: """ Transfers an owned unique gift to another user. Requires the can_transfer_and_upgrade_gifts business bot right. @@ -8106,7 +8106,7 @@ async def transfer_gift( :type owned_gift_id: :obj:`str` :param new_owner_chat_id: Unique identifier of the chat which will own the gift. The chat must be active in the last 24 hours. - :type new_owner_chat_id: :obj:`int` | :obj:`str` + :type new_owner_chat_id: :obj:`int` :param star_count: The amount of Telegram Stars that will be paid for the transfer from the business account balance. If positive, then the can_transfer_stars business bot right is required. @@ -8117,7 +8117,7 @@ async def transfer_gift( """ return await asyncio_helper.transfer_gift( self.token, business_connection_id, owned_gift_id, - new_owner_chat_id=new_owner_chat_id, + new_owner_chat_id, star_count=star_count ) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 67990da54..c582aa3e4 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1993,20 +1993,24 @@ async def set_business_account_name(token, business_connection_id, first_name, l return await _process_request(token, method_url, params=payload, method='post') -async def set_business_account_username(token, business_connection_id, username): +async def set_business_account_username(token, business_connection_id, username=None): method_url = 'setBusinessAccountUsername' - payload = {'business_connection_id': business_connection_id, 'username': username} + payload = {'business_connection_id': business_connection_id} + if username is not None: + payload['username'] = username return await _process_request(token, method_url, params=payload, method='post') -async def set_business_account_bio(token, business_connection_id, bio): +async def set_business_account_bio(token, business_connection_id, bio=None): method_url = 'setBusinessAccountBio' - payload = {'business_connection_id': business_connection_id, 'bio': bio} + payload = {'business_connection_id': business_connection_id} + if bio: + payload['bio'] = bio return await _process_request(token, method_url, params=payload, method='post') async def set_business_account_gift_settings(token, business_connection_id, show_gift_button, accepted_gift_types): method_url = 'setBusinessAccountGiftSettings' - payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, 'accepted_gift_types': json.dumps(accepted_gift_types)} + payload = {'business_connection_id': business_connection_id, 'show_gift_button': show_gift_button, 'accepted_gift_types': accepted_gift_types.to_json()} return await _process_request(token, method_url, params=payload, method='post') async def get_business_account_star_balance(token, business_connection_id): diff --git a/telebot/types.py b/telebot/types.py index 2939c9e5f..ff24374a8 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -688,7 +688,7 @@ class ChatFullInfo(JsonDeserializable): :param permissions: Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. :type permissions: :class:`telebot.types.ChatPermissions` - :param can_send_gift: Optional. True, if gifts can be sent to the chat + :param can_send_gift: deprecated, use accepted_gift_types instead. :type can_send_gift: :obj:`bool` :param accepted_gift_types: Information about types of gifts that are accepted by the chat or by the corresponding user for private chats @@ -829,10 +829,17 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.birthdate: Optional[Birthdate] = birthdate self.can_send_paid_media: Optional[bool] = can_send_paid_media self.accepted_gift_types: AcceptedGiftTypes = accepted_gift_types - self.can_send_gift: Optional[bool] = None - if self.accepted_gift_types is not None: # not optional but still - # skip premium subscription? - self.can_send_gift: Optional[bool] = any([self.accepted_gift_types.unique_gifts, self.accepted_gift_types.unlimited_gifts, self.accepted_gift_types.limited_gifts]) + @property + def can_send_gift(self) -> bool: + """ + Deprecated. Use `accepted_gift_types` instead. + + :return: True if the chat can send gifts + """ + log_deprecation_warning("The parameter 'can_send_gift' is deprecated. Use 'accepted_gift_types' instead.") + if self.accepted_gift_types is not None: # just in case + return any([self.accepted_gift_types.unique_gifts, self.accepted_gift_types.unlimited_gifts, self.accepted_gift_types.limited_gifts]) + return False class Chat(ChatFullInfo): @@ -9774,7 +9781,7 @@ class BusinessConnection(JsonDeserializable): :param date: Date the connection was established in Unix time :type date: :obj:`int` - :param can_reply: Deprecated, use :attr:`can_reply` instead. True, if the bot can reply to messages from the business account + :param can_reply: Deprecated, use :attr:`rights` instead. True, if the bot can reply to messages from the business account :type can_reply: :obj:`bool` :param rights: Optional. Rights of the business bot @@ -9792,6 +9799,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) + obj['rights'] = BusinessBotRights.de_json(obj.get('rights')) return cls(**obj) def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, @@ -9801,10 +9809,16 @@ def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, self.user_chat_id: int = user_chat_id self.date: int = date self.rights: Optional[BusinessBotRights] = rights - # Deprecated, use self.rights instead - self.can_reply: Optional[bool] = can_reply self.is_enabled: bool = is_enabled + @property + def can_reply(self) -> bool: + """ + Deprecated, use :attr:`rights` instead. + """ + log_deprecation_warning('The field "can_reply" is deprecated, use "rights" instead') + return self.rights is not None and self.rights.can_reply + class BusinessMessagesDeleted(JsonDeserializable): @@ -11426,8 +11440,8 @@ class AcceptedGiftTypes(JsonDeserializable, JsonSerializable): :return: Instance of the class :rtype: :class:`AcceptedGiftTypes` """ - def __init__(self, unlimited_gifts: Optional[bool] = None, limited_gifts: Optional[bool] = None, - unique_gifts: Optional[bool] = None, premium_subscription: Optional[bool] = None, **kwargs): + def __init__(self, unlimited_gifts: Optional[bool], limited_gifts: Optional[bool], + unique_gifts: Optional[bool], premium_subscription: Optional[bool], **kwargs): self.unlimited_gifts: Optional[bool] = unlimited_gifts self.limited_gifts: Optional[bool] = limited_gifts self.unique_gifts: Optional[bool] = unique_gifts @@ -11437,15 +11451,12 @@ def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): - data = {} - if self.unlimited_gifts is not None: - data['unlimited_gifts'] = self.unlimited_gifts - if self.limited_gifts is not None: - data['limited_gifts'] = self.limited_gifts - if self.unique_gifts is not None: - data['unique_gifts'] = self.unique_gifts - if self.premium_subscription is not None: - data['premium_subscription'] = self.premium_subscription + data = { + 'unlimited_gifts': self.unlimited_gifts, + 'limited_gifts': self.limited_gifts, + 'unique_gifts': self.unique_gifts, + 'premium_subscription': self.premium_subscription + } return data @classmethod def de_json(cls, json_string): @@ -11479,7 +11490,7 @@ def de_json(cls, json_string): return cls(**obj) -class OwnedGift(JsonDeserializable): +class OwnedGift(JsonDeserializable, ABC): """ This object describes a gift received and owned by a user or a chat. Currently, it can be one of OwnedGiftRegular @@ -11487,6 +11498,10 @@ class OwnedGift(JsonDeserializable): Telegram documentation: https://core.telegram.org/bots/api#ownedgift """ + + def __init__(self, type, **kwargs): + self.type: str = type + self.gift: Union[Gift, UniqueGift] = None @classmethod @@ -11549,7 +11564,7 @@ class OwnedGiftRegular(OwnedGift): def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=None, text=None, entities=None, is_private=None, is_saved=None, can_be_upgraded=None, was_refunded=None, convert_star_count=None, prepaid_upgrade_star_count=None, **kwargs): - self.type: str = type + super().__init__(type=type) self.gift: Gift = gift self.owned_gift_id: Optional[str] = owned_gift_id self.sender_user: Optional[User] = sender_user @@ -11608,7 +11623,7 @@ class OwnedGiftUnique(OwnedGift): """ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=None, is_saved=None, can_be_transferred=None, transfer_star_count=None, **kwargs): - self.type: str = type + super().__init__(type=type) self.gift: UniqueGift = gift self.owned_gift_id: Optional[str] = owned_gift_id self.sender_user: Optional[User] = sender_user @@ -11823,7 +11838,7 @@ def de_json(cls, json_string): obj['colors'] = UniqueGiftBackdropColors.de_json(obj['colors']) return cls(**obj) -class InputStoryContent(JsonSerializable): +class InputStoryContent(JsonSerializable, ABC): """ This object describes the content of a story to post. Currently, it can be one of InputStoryContentPhoto @@ -11832,6 +11847,8 @@ class InputStoryContent(JsonSerializable): Telegram documentation: https://core.telegram.org/bots/api#inputstorycontent """ + def __init__(self, type: str, **kwargs): + self.type: str = type class InputStoryContentPhoto(InputStoryContent): @@ -11841,13 +11858,13 @@ class InputStoryContentPhoto(InputStoryContent): Telegram documentation: https://core.telegram.org/bots/api#inputstorycontentphoto :param photo: The photo to post as a story. The photo must be of the size 1080x1920 and must not exceed 10 MB. The photo can't be reused and can only be uploaded as a new file, so you can pass “attach://” if the photo was uploaded using multipart/form-data under . More information on Sending Files - :type photo: :obj:`str` + :type photo: :class:`telebot.types.InputFile` :return: Instance of the class :rtype: :class:`InputStoryContentPhoto` """ def __init__(self, photo: InputFile, **kwargs): - self.type: str = "photo" + super().__init__(type="photo") self.photo: InputFile = photo self._photo_name = service_utils.generate_random_token() self._photo_dic = "attach://{}".format(self._photo_name) @@ -11873,7 +11890,7 @@ class InputStoryContentVideo(InputStoryContent): Telegram documentation: https://core.telegram.org/bots/api#inputstorycontentvideo :param video: The video to post as a story. The video must be of the size 720x1280, streamable, encoded with H.265 codec, with key frames added each second in the MPEG4 format, and must not exceed 30 MB. The video can't be reused and can only be uploaded as a new file, so you can pass “attach://” if the video was uploaded using multipart/form-data under . More information on Sending Files - :type video: :obj:`str` + :type video: :class:`telebot.types.InputFile` :param duration: Optional. Precise duration of the video in seconds; 0-60 :type duration: :obj:`float` @@ -11889,7 +11906,7 @@ class InputStoryContentVideo(InputStoryContent): """ def __init__(self, video: InputFile, duration: Optional[float] = None, cover_frame_timestamp: Optional[float] = None, is_animation: Optional[bool] = None, **kwargs): - self.type: str = "video" + super().__init__(type="video") self.video: InputFile = video self._video_name = service_utils.generate_random_token() self._video_dic = "attach://{}".format(self._video_name) @@ -11997,7 +12014,7 @@ def to_dict(self): data = { 'country_code': self.country_code } - if self.state is not None: + if self.state: data['state'] = self.state if self.city is not None: data['city'] = self.city @@ -12005,7 +12022,7 @@ def to_dict(self): data['street'] = self.street return data -class StoryAreaType(JsonSerializable): +class StoryAreaType(JsonSerializable, ABC): """ Describes the type of a clickable area on a story. Currently, it can be one of StoryAreaTypeLocation @@ -12019,6 +12036,8 @@ class StoryAreaType(JsonSerializable): :return: Instance of the class :rtype: :class:`StoryArea` """ + def __init__(self, type: str, **kwargs): + self.type: str = type class StoryAreaTypeLocation(StoryAreaType): @@ -12036,17 +12055,17 @@ class StoryAreaTypeLocation(StoryAreaType): :param longitude: Location longitude in degrees :type longitude: :obj:`float` - :param address: Location address + :param address: Optional, Location address :type address: :class:`LocationAddress` :return: Instance of the class :rtype: :class:`StoryAreaTypeLocation` """ - def __init__(self,latitude: float, longitude: float, address: LocationAddress, **kwargs): - self.type: str = "location" + def __init__(self,latitude: float, longitude: float, address: LocationAddress = None, **kwargs): + super().__init__(type="location") self.latitude: float = latitude self.longitude: float = longitude - self.address: LocationAddress = address + self.address: Optional[LocationAddress] = address def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): @@ -12054,8 +12073,9 @@ def to_dict(self): 'type': self.type, 'latitude': self.latitude, 'longitude': self.longitude, - 'address': self.address.to_dict() } + if self.address is not None: + data['address'] = self.address.to_dict() return data @@ -12081,7 +12101,7 @@ class StoryAreaTypeSuggestedReaction(StoryAreaType): :rtype: :class:`StoryAreaTypeSuggestedReaction` """ def __init__(self, reaction_type: ReactionType, is_dark: Optional[bool] = None, is_flipped: Optional[bool] = None, **kwargs): - self.type: str = "suggested_reaction" + super().__init__(type="suggested_reaction") self.reaction_type: ReactionType = reaction_type self.is_dark: Optional[bool] = is_dark self.is_flipped: Optional[bool] = is_flipped @@ -12114,7 +12134,7 @@ class StoryAreaTypeLink(StoryAreaType): :rtype: :class:`StoryAreaTypeLink` """ def __init__(self, url: str, **kwargs): - self.type: str = "link" + super().__init__(type="link") self.url: str = url def to_json(self): return json.dumps(self.to_dict()) @@ -12147,7 +12167,7 @@ class StoryAreaTypeWeather(StoryAreaType): :rtype: :class:`StoryAreaTypeWeather` """ def __init__(self, temperature: float, emoji: str, background_color: int, **kwargs): - self.type: str = "weather" + super().__init__(type="weather") self.temperature: float = temperature self.emoji: str = emoji self.background_color: int = background_color @@ -12178,7 +12198,7 @@ class StoryAreaTypeUniqueGift(StoryAreaType): :rtype: :class:`StoryAreaTypeUniqueGift` """ def __init__(self, name: str, **kwargs): - self.type: str = "unique_gift" + super().__init__(type="unique_gift") self.name: str = name def to_json(self): return json.dumps(self.to_dict()) From d4f5ead9c10ba73fead33f77df9474823ac0a0c3 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 20 Apr 2025 01:18:33 +0400 Subject: [PATCH 436/480] Fix typehints --- telebot/types.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index ff24374a8..817688351 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11440,12 +11440,12 @@ class AcceptedGiftTypes(JsonDeserializable, JsonSerializable): :return: Instance of the class :rtype: :class:`AcceptedGiftTypes` """ - def __init__(self, unlimited_gifts: Optional[bool], limited_gifts: Optional[bool], - unique_gifts: Optional[bool], premium_subscription: Optional[bool], **kwargs): - self.unlimited_gifts: Optional[bool] = unlimited_gifts - self.limited_gifts: Optional[bool] = limited_gifts - self.unique_gifts: Optional[bool] = unique_gifts - self.premium_subscription: Optional[bool] = premium_subscription + def __init__(self, unlimited_gifts: bool, limited_gifts: bool, + unique_gifts: bool, premium_subscription: bool, **kwargs): + self.unlimited_gifts: bool = unlimited_gifts + self.limited_gifts: bool = limited_gifts + self.unique_gifts: bool = unique_gifts + self.premium_subscription: bool = premium_subscription def to_json(self): return json.dumps(self.to_dict()) From f6906ecf6415540cb8f02d9ebfb32be924b4c45f Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sun, 20 Apr 2025 00:44:59 +0300 Subject: [PATCH 437/480] Bump version to 4.27 --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 0ce35e8db..000225031 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.26.0' +release = '4.27.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 471aaa45b..e7bf04f85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.26.0" +version = "4.27.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index b37f3e662..e0fe9ac48 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.26.0' +__version__ = '4.27.0' From 93ce320302872f66cdc805834bfd02c24b2c65bb Mon Sep 17 00:00:00 2001 From: Badiboy Date: Mon, 21 Apr 2025 11:00:04 +0300 Subject: [PATCH 438/480] Fix states functions with new parameters ... and some minor issues. --- telebot/__init__.py | 40 ++++++++++++++----------- telebot/async_telebot.py | 40 +++++++++++++++---------- telebot/asyncio_storage/base_storage.py | 36 ++++++++++++++++++---- telebot/states/asyncio/context.py | 4 +-- telebot/storage/base_storage.py | 36 ++++++++++++++++++---- 5 files changed, 109 insertions(+), 47 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 5a3064c48..8b651a5b0 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -5564,7 +5564,7 @@ def create_invoice_link(self, # noinspection PyShadowingBuiltins def send_poll( - self, chat_id: Union[int, str], question: str, options: List[types.InputPollOption], + self, chat_id: Union[int, str], question: str, options: List[Union[str, types.InputPollOption]], is_anonymous: Optional[bool]=None, type: Optional[str]=None, allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, @@ -5600,7 +5600,7 @@ def send_poll( :type question: :obj:`str` :param options: A JSON-serialized list of 2-10 answer options - :type options: :obj:`list` of :obj:`InputPollOption` + :type options: :obj:`list` of :obj:`InputPollOption` | :obj:`list` of :obj:`str` :param is_anonymous: True, if the poll needs to be anonymous, defaults to True :type is_anonymous: :obj:`bool` @@ -7578,9 +7578,8 @@ def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[in chat_id = user_id if bot_id is None: bot_id = self.bot_id - return self.current_states.set_state( - chat_id=chat_id, user_id=user_id, state=state, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return self.current_states.set_state(chat_id, user_id, state, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def reset_data(self, user_id: int, chat_id: Optional[int]=None, @@ -7611,8 +7610,8 @@ def reset_data(self, user_id: int, chat_id: Optional[int]=None, chat_id = user_id if bot_id is None: bot_id = self.bot_id - return self.current_states.reset_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return self.current_states.reset_data(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, @@ -7630,6 +7629,15 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_conne :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier, defaults to current bot id + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: True on success :rtype: :obj:`bool` """ @@ -7637,8 +7645,8 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_conne chat_id = user_id if bot_id is None: bot_id = self.bot_id - return self.current_states.delete_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return self.current_states.delete_state(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, @@ -7668,9 +7676,8 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn chat_id = user_id if bot_id is None: bot_id = self.bot_id - return self.current_states.get_interactive_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, - message_thread_id=message_thread_id) + return self.current_states.get_interactive_data(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def get_state(self, user_id: int, chat_id: Optional[int]=None, @@ -7707,8 +7714,8 @@ def get_state(self, user_id: int, chat_id: Optional[int]=None, chat_id = user_id if bot_id is None: bot_id = self.bot_id - return self.current_states.get_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return self.current_states.get_state(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def add_data(self, user_id: int, chat_id: Optional[int]=None, @@ -7742,8 +7749,8 @@ def add_data(self, user_id: int, chat_id: Optional[int]=None, if bot_id is None: bot_id = self.bot_id for key, value in kwargs.items(): - self.current_states.set_data(chat_id=chat_id, user_id=user_id, key=key, value=value, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + self.current_states.set_data(chat_id, user_id, key, value, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def register_next_step_handler_by_chat_id( @@ -9848,4 +9855,3 @@ def _notify_command_handlers(self, handlers, new_messages, update_type): handlers=handlers, middlewares=middlewares, update_type=update_type) - diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 26e34934b..8c021b9a7 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -8,6 +8,7 @@ import sys # this imports are used to avoid circular import error +# noinspection PyUnresolvedReferences import telebot.util import telebot.types @@ -7008,7 +7009,7 @@ async def create_invoice_link(self, # noinspection PyShadowingBuiltins async def send_poll( - self, chat_id: Union[int, str], question: str, options: List[types.InputPollOption], + self, chat_id: Union[int, str], question: str, options: List[Union[str, types.InputPollOption]], is_anonymous: Optional[bool]=None, type: Optional[str]=None, allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, @@ -7044,7 +7045,7 @@ async def send_poll( :type question: :obj:`str` :param options: A JSON-serialized list of 2-10 answer options - :type options: :obj:`list` of :obj:`InputPollOption` + :type options: :obj:`list` of :obj:`InputPollOption` | :obj:`list` of :obj:`str` :param is_anonymous: True, if the poll needs to be anonymous, defaults to True :type is_anonymous: :obj:`bool` @@ -8828,9 +8829,8 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: chat_id = user_id if bot_id is None: bot_id = self.bot_id - return await self.current_states.set_state( - chat_id=chat_id, user_id=user_id, state=state, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return await self.current_states.set_state(chat_id, user_id, state, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) async def reset_data(self, user_id: int, chat_id: Optional[int]=None, @@ -8861,8 +8861,8 @@ async def reset_data(self, user_id: int, chat_id: Optional[int]=None, chat_id = user_id if bot_id is None: bot_id = self.bot_id - return await self.current_states.reset_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return await self.current_states.reset_data(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) async def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, @@ -8876,14 +8876,23 @@ async def delete_state(self, user_id: int, chat_id: Optional[int]=None, business :param chat_id: Chat's identifier :type chat_id: :obj:`int` + :param bot_id: Bot's identifier, defaults to current bot id + :type bot_id: :obj:`int` + + :param business_connection_id: Business identifier + :type business_connection_id: :obj:`str` + + :param message_thread_id: Identifier of the message thread + :type message_thread_id: :obj:`int` + :return: None """ if chat_id is None: chat_id = user_id if bot_id is None: bot_id = self.bot_id - return await self.current_states.delete_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return await self.current_states.delete_state(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, @@ -8913,9 +8922,8 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn chat_id = user_id if bot_id is None: bot_id = self.bot_id - return self.current_states.get_interactive_data(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, - message_thread_id=message_thread_id) + return self.current_states.get_interactive_data(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) async def get_state(self, user_id: int, chat_id: Optional[int]=None, @@ -8952,8 +8960,8 @@ async def get_state(self, user_id: int, chat_id: Optional[int]=None, chat_id = user_id if bot_id is None: bot_id = self.bot_id - return await self.current_states.get_state(chat_id=chat_id, user_id=user_id, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + return await self.current_states.get_state(chat_id, user_id, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) async def add_data(self, user_id: int, chat_id: Optional[int]=None, @@ -8987,5 +8995,5 @@ async def add_data(self, user_id: int, chat_id: Optional[int]=None, if bot_id is None: bot_id = self.bot_id for key, value in kwargs.items(): - await self.current_states.set_data(chat_id=chat_id, user_id=user_id, key=key, value=value, bot_id=bot_id, - business_connection_id=business_connection_id, message_thread_id=message_thread_id) + await self.current_states.set_data(chat_id, user_id, key, value, + bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) diff --git a/telebot/asyncio_storage/base_storage.py b/telebot/asyncio_storage/base_storage.py index 20d0b0587..191ac45f4 100644 --- a/telebot/asyncio_storage/base_storage.py +++ b/telebot/asyncio_storage/base_storage.py @@ -5,7 +5,11 @@ class StateStorageBase: def __init__(self) -> None: pass - async def set_data(self, chat_id, user_id, key, value): + async def set_data(self, chat_id, user_id, key, value, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Set data for a user in a particular chat. """ @@ -17,7 +21,11 @@ async def get_data(self, chat_id, user_id): """ raise NotImplementedError - async def set_state(self, chat_id, user_id, state): + async def set_state(self, chat_id, user_id, state, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Set state for a particular user. @@ -28,22 +36,38 @@ async def set_state(self, chat_id, user_id, state): """ raise NotImplementedError - async def delete_state(self, chat_id, user_id): + async def delete_state(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Delete state for a particular user. """ raise NotImplementedError - async def reset_data(self, chat_id, user_id): + async def reset_data(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Reset data for a particular user in a chat. """ raise NotImplementedError - async def get_state(self, chat_id, user_id): + async def get_state(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): raise NotImplementedError - def get_interactive_data(self, chat_id, user_id): + def get_interactive_data(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Should be sync, but should provide a context manager with __aenter__ and __aexit__ methods. diff --git a/telebot/states/asyncio/context.py b/telebot/states/asyncio/context.py index 4c9ad61a3..50f252021 100644 --- a/telebot/states/asyncio/context.py +++ b/telebot/states/asyncio/context.py @@ -1,4 +1,4 @@ -from telebot.states import State, StatesGroup +from telebot.states import State from telebot.types import CallbackQuery, Message from telebot.async_telebot import AsyncTeleBot from telebot.states import resolve_context @@ -21,7 +21,7 @@ async def start_ex(message: types.Message, state_context: StateContext): # also, state_context.data(), .add_data(), .reset_data(), .delete() methods available. """ - def __init__(self, message: Union[Message, CallbackQuery], bot: str) -> None: + def __init__(self, message: Union[Message, CallbackQuery], bot: AsyncTeleBot) -> None: self.message: Union[Message, CallbackQuery] = message self.bot: AsyncTeleBot = bot self.bot_id = self.bot.bot_id diff --git a/telebot/storage/base_storage.py b/telebot/storage/base_storage.py index 9956c7ab9..033f63231 100644 --- a/telebot/storage/base_storage.py +++ b/telebot/storage/base_storage.py @@ -5,7 +5,11 @@ class StateStorageBase: def __init__(self) -> None: pass - def set_data(self, chat_id, user_id, key, value): + def set_data(self, chat_id, user_id, key, value, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Set data for a user in a particular chat. """ @@ -17,7 +21,11 @@ def get_data(self, chat_id, user_id): """ raise NotImplementedError - def set_state(self, chat_id, user_id, state): + def set_state(self, chat_id, user_id, state, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Set state for a particular user. @@ -28,22 +36,38 @@ def set_state(self, chat_id, user_id, state): """ raise NotImplementedError - def delete_state(self, chat_id, user_id): + def delete_state(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Delete state for a particular user. """ raise NotImplementedError - def reset_data(self, chat_id, user_id): + def reset_data(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): """ Reset data for a particular user in a chat. """ raise NotImplementedError - def get_state(self, chat_id, user_id): + def get_state(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): raise NotImplementedError - def get_interactive_data(self, chat_id, user_id): + def get_interactive_data(self, chat_id, user_id, + business_connection_id=None, + message_thread_id=None, + bot_id=None, + ): raise NotImplementedError def save(self, chat_id, user_id, data): From e5a02fa19073d7395baec737261cf6ef5b0a1ba2 Mon Sep 17 00:00:00 2001 From: "g.zinovev" Date: Tue, 6 May 2025 13:21:16 +0300 Subject: [PATCH 439/480] Address maintainer feedback: [fixed optional values] --- telebot/types.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 2cd6b8066..0d0361dcb 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6703,13 +6703,14 @@ def __init__(self, type, media, caption=None, parse_mode=None, caption_entities= self.caption_entities: Optional[List[MessageEntity]] = caption_entities self.thumbnail: Optional[Union[str, InputFile]] = thumbnail - if isinstance(self.thumbnail, InputFile): - self._thumbnail_name = service_utils.generate_random_token() - self._thumbnail_dic = 'attach://{0}'.format(self._thumbnail_name) - else: + if service_utils.is_string(self.thumbnail): self._thumbnail_name = '' self._thumbnail_dic = self.thumbnail + else: + self._thumbnail_name = service_utils.generate_random_token() + self._thumbnail_dic = 'attach://{0}'.format(self._thumbnail_name) + if service_utils.is_string(self.media): self._media_name = '' self._media_dic = self.media @@ -6721,7 +6722,9 @@ def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): - json_dict = {'type': self.type, 'media': self._media_dic, 'thumbnail': self._thumbnail_dic} + json_dict = {'type': self.type, 'media': self._media_dic} + if self._thumbnail_dic: + json_dict['thumbnail'] = self._thumbnail_dic if self.caption: json_dict['caption'] = self.caption if self.parse_mode: @@ -6736,8 +6739,12 @@ def convert_input_media(self): """ if service_utils.is_string(self.media): return self.to_json(), None + + media_dict = {self._media_name: self.media} + if self._thumbnail_name: + media_dict[self._thumbnail_name] = self.thumbnail - return self.to_json(), {self._media_name: self.media, self._thumbnail_name: self.thumbnail} + return self.to_json(), media_dict class InputMediaPhoto(InputMedia): From ded461fcc1e6a48ec86e50f3495055f0688e30fe Mon Sep 17 00:00:00 2001 From: "g.zinovev" Date: Tue, 6 May 2025 22:52:02 +0300 Subject: [PATCH 440/480] Address maintainer feedback: [fixed thumbnail is None] --- telebot/types.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 0d0361dcb..2cd194d21 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -6703,10 +6703,12 @@ def __init__(self, type, media, caption=None, parse_mode=None, caption_entities= self.caption_entities: Optional[List[MessageEntity]] = caption_entities self.thumbnail: Optional[Union[str, InputFile]] = thumbnail - if service_utils.is_string(self.thumbnail): + if thumbnail is None: + self._thumbnail_name = '' + self._thumbnail_dic = None + elif service_utils.is_string(self.thumbnail): self._thumbnail_name = '' self._thumbnail_dic = self.thumbnail - else: self._thumbnail_name = service_utils.generate_random_token() self._thumbnail_dic = 'attach://{0}'.format(self._thumbnail_name) From ad5a711b8c0ea128b5f5447d4e198a197b17e738 Mon Sep 17 00:00:00 2001 From: Roman A <121314722+GameRoMan@users.noreply.github.com> Date: Wed, 7 May 2025 18:04:55 +0100 Subject: [PATCH 441/480] Fix type annotations --- telebot/__init__.py | 4 ++-- telebot/util.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 8b651a5b0..0dffa65ac 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -3528,7 +3528,7 @@ def edit_message_live_location( proximity_alert_radius: Optional[int]=None, live_period: Optional[int]=None, business_connection_id: Optional[str]=None - ) -> types.Message or bool: + ) -> Union[types.Message, bool]: """ Use this method to edit live location messages. A location can be edited until its live_period expires or editing is explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message is not an inline message, the edited Message @@ -3590,7 +3590,7 @@ def stop_message_live_location( inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, - business_connection_id: Optional[str]=None) -> types.Message or bool: + business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: """ Use this method to stop updating a live location message before live_period expires. On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. diff --git a/telebot/util.py b/telebot/util.py index bed0e8c19..8daf1d43c 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -255,7 +255,7 @@ def extract_command(text: str) -> Union[str, None]: return text.split()[0].split('@')[0][1:] if is_command(text) else None -def extract_arguments(text: str) -> str or None: +def extract_arguments(text: str) -> Union[str, None]: """ Returns the argument after the command. From b1392b232a56883a5c181f584a3e127147dfc60e Mon Sep 17 00:00:00 2001 From: Mohammad Date: Fri, 16 May 2025 17:43:10 +0200 Subject: [PATCH 442/480] Add py.typed marker file for PEP 561 compatibility This file signals to type checkers that the library provides inline type hints and should be type-checked, improving integration with tools like Mypy. --- telebot/py.typed | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 telebot/py.typed diff --git a/telebot/py.typed b/telebot/py.typed new file mode 100644 index 000000000..e69de29bb From 5f2c4882beabc6a735a62e0b1bfd4e3860a7c6df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 08:15:48 +0000 Subject: [PATCH 443/480] Bump requests from 2.32.0 to 2.32.4 Bumps [requests](https://github.com/psf/requests) from 2.32.0 to 2.32.4. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.32.0...v2.32.4) --- updated-dependencies: - dependency-name: requests dependency-version: 2.32.4 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 55dd7e486..febcca257 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest -requests==2.32.0 +requests==2.32.4 wheel==0.38.1 aiohttp==3.10.11 From 9e7f570d51c072303b676510bc90408ab66b011b Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 4 Jul 2025 21:41:25 +0500 Subject: [PATCH 444/480] Bot API 9.1 changes --- telebot/__init__.py | 97 ++++++++++- telebot/apihelper.py | 34 ++++ telebot/async_telebot.py | 94 ++++++++++- telebot/asyncio_helper.py | 34 ++++ telebot/types.py | 330 +++++++++++++++++++++++++++++++++++++- 5 files changed, 581 insertions(+), 8 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 0dffa65ac..59a8d7db8 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2104,6 +2104,90 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) return [types.MessageID.de_json(message_id) for message_id in result] + def send_checklist( + self, business_connection_id: str, chat_id: Union[int, str], + checklist: types.InputChecklist, + disable_notification: Optional[bool]=None, + protect_content: Optional[bool]=None, + message_effect_id: Optional[str]=None, + reply_parameters: Optional[types.ReplyParameters]=None, + reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> types.Message: + """ + Use this method to send a checklist on behalf of a connected business account. On success, + the sent Message is returned. + + Telegram documentation: https://core.telegram.org/bots/api#sendchecklist + + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be sent + :type business_connection_id: :obj:`str` + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param checklist: A JSON-serialized object for the checklist to send + :type checklist: :class:`telebot.types.InputChecklist` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound. + :type disable_notification: :obj:`bool` + + :param protect_content: Protects the contents of the sent message from forwarding and saving + :type protect_content: :obj:`bool` + + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + + :param reply_parameters: Additional parameters for replies to messages + :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard. + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` + + :return: On success, the sent Message is returned. + :rtype: :class:`telebot.types.Message` + """ + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification + protect_content = self.protect_content if (protect_content is None) else protect_content + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + + return types.Message.de_json( + apihelper.send_checklist( + self.token, business_connection_id, chat_id, checklist, disable_notification=disable_notification, + protect_content=protect_content, message_effect_id=message_effect_id, + reply_parameters=reply_parameters, reply_markup=reply_markup)) + + def edit_message_checklist( + self, business_connection_id: str, chat_id: Union[int, str], + message_id: int, checklist: types.InputChecklist, + reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> types.Message: + """ + Use this method to edit a checklist on behalf of a connected business account. On success, + the edited Message is returned. + + Telegram documentation: https://core.telegram.org/bots/api#editmessagechecklist + + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be sent + :type business_connection_id: :obj:`str` + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Unique identifier for the target message + :type message_id: :obj:`int` + + :param checklist: A JSON-serialized object for the new checklist + :type checklist: :class:`telebot.types.InputChecklist` + + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard. + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` + + :return: On success, the edited Message is returned. + :rtype: :class:`telebot.types.Message` + """ + return types.Message.de_json( + apihelper.edit_message_checklist( + self.token, business_connection_id, chat_id, message_id, checklist, reply_markup=reply_markup)) def send_dice( self, chat_id: Union[int, str], @@ -5599,7 +5683,7 @@ def send_poll( :param question: Poll question, 1-300 characters :type question: :obj:`str` - :param options: A JSON-serialized list of 2-10 answer options + :param options: A JSON-serialized list of 2-12 answer options :type options: :obj:`list` of :obj:`InputPollOption` | :obj:`list` of :obj:`str` :param is_anonymous: True, if the poll needs to be anonymous, defaults to True @@ -5818,6 +5902,17 @@ def answer_pre_checkout_query( """ return apihelper.answer_pre_checkout_query( self.token, pre_checkout_query_id, ok, error_message=error_message) + + def get_my_star_balance(self) -> types.StarAmount: + """ + Returns the bot's current Telegram Stars balance. On success, returns a StarAmount object. + + Telegram documentation: https://core.telegram.org/bots/api#getmystarbalance + + :return: On success, returns a StarAmount object. + :rtype: :obj:`types.StarAmount` + """ + return types.StarAmount.de_json(apihelper.get_my_star_balance(self.token)) def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int]=None) -> types.StarTransactions: diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 460c3c4a6..634b805d3 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -473,6 +473,36 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['video_start_timestamp'] = video_start_timestamp return _make_request(token, method_url, params=payload) +def send_checklist( + token, business_connection_id, chat_id, checklist, + disable_notification=None, protect_content=None, message_effect_id=None, + reply_parameters=None, reply_markup=None +): + method_url = r'sendChecklist' + payload = {'chat_id': chat_id, 'checklist': checklist, 'business_connection_id': business_connection_id} + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if protect_content is not None: + payload['protect_content'] = protect_content + if message_effect_id is not None: + payload['message_effect_id'] = message_effect_id + if reply_parameters is not None: + payload['reply_parameters'] = reply_parameters.to_json() + if reply_markup is not None: + payload['reply_markup'] = _convert_markup(reply_markup) + return _make_request(token, method_url, params=payload) + + +def edit_message_checklist( + token, business_connection_id, chat_id, message_id, checklist, + reply_markup=None +): + method_url = r'editMessageChecklist' + payload = {'chat_id': chat_id, 'message_id': message_id, 'checklist': checklist, 'business_connection_id': business_connection_id} + if reply_markup is not None: + payload['reply_markup'] = await _convert_markup(reply_markup) + return _make_request(token, method_url, params=payload) + def send_dice( token, chat_id, @@ -1817,6 +1847,10 @@ def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_message=No payload['error_message'] = error_message return _make_request(token, method_url, params=payload) +def get_my_star_balance(token): + method_url = 'getMyStarBalance' + return _make_request(token, method_url) + def get_star_transactions(token, offset=None, limit=None): method_url = 'getStarTransactions' payload = {} diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 8c021b9a7..fe8013135 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3619,6 +3619,91 @@ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, protect_content, remove_caption) return [types.MessageID.de_json(message_id) for message_id in result] + + async def send_checklist( + self, business_connection_id: str, chat_id: Union[int, str], + checklist: types.InputChecklist, + disable_notification: Optional[bool]=None, + protect_content: Optional[bool]=None, + message_effect_id: Optional[str]=None, + reply_parameters: Optional[types.ReplyParameters]=None, + reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> types.Message: + """ + Use this method to send a checklist on behalf of a connected business account. On success, + the sent Message is returned. + + Telegram documentation: https://core.telegram.org/bots/api#sendchecklist + + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be sent + :type business_connection_id: :obj:`str` + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param checklist: A JSON-serialized object for the checklist to send + :type checklist: :class:`telebot.types.InputChecklist` + + :param disable_notification: Sends the message silently. Users will receive a notification with no sound. + :type disable_notification: :obj:`bool` + + :param protect_content: Protects the contents of the sent message from forwarding and saving + :type protect_content: :obj:`bool` + + :param message_effect_id: Unique identifier of the message effect to be added to the message; for private chats only + :type message_effect_id: :obj:`str` + + :param reply_parameters: Additional parameters for replies to messages + :type reply_parameters: :class:`telebot.types.ReplyParameters` + + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard. + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` + + :return: On success, the sent Message is returned. + :rtype: :class:`telebot.types.Message` + """ + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification + protect_content = self.protect_content if (protect_content is None) else protect_content + + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): + reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply + + return types.Message.de_json( + await asyncio_helper.send_checklist( + self.token, business_connection_id, chat_id, checklist, disable_notification=disable_notification, + protect_content=protect_content, message_effect_id=message_effect_id, + reply_parameters=reply_parameters, reply_markup=reply_markup)) + + async def edit_message_checklist( + self, business_connection_id: str, chat_id: Union[int, str], + message_id: int, checklist: types.InputChecklist, + reply_markup: Optional[types.InlineKeyboardMarkup]=None) -> types.Message: + """ + Use this method to edit a checklist on behalf of a connected business account. On success, + the edited Message is returned. + + Telegram documentation: https://core.telegram.org/bots/api#editmessagechecklist + + :param business_connection_id: Unique identifier of the business connection on behalf of which the message will be sent + :type business_connection_id: :obj:`str` + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Unique identifier for the target message + :type message_id: :obj:`int` + + :param checklist: A JSON-serialized object for the new checklist + :type checklist: :class:`telebot.types.InputChecklist` + + :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard. + :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` + + :return: On success, the edited Message is returned. + :rtype: :class:`telebot.types.Message` + """ + return types.Message.de_json( + await asyncio_helper.edit_message_checklist( + self.token, business_connection_id, chat_id, message_id, checklist, reply_markup=reply_markup)) async def send_dice( self, chat_id: Union[int, str], @@ -7256,8 +7341,15 @@ async def answer_pre_checkout_query( :rtype: :obj:`bool` """ return await asyncio_helper.answer_pre_checkout_query(self.token, pre_checkout_query_id, ok, error_message) - + + async def get_my_star_balance(self) -> types.StarAmount: + """ + A method to get the current Telegram Stars balance of the bot. Requires no parameters. + On success, returns a StarAmount object. + """ + return types.StarAmount.de_json(await asyncio_helper.get_my_star_balance(self.token)) + async def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int]=None) -> types.StarTransactions: """ Returns the bot's Telegram Star transactions in chronological order. diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index c582aa3e4..4a542ffcf 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -477,6 +477,35 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['video_start_timestamp'] = video_start_timestamp return await _process_request(token, method_url, params=payload) +async def send_checklist( + token, business_connection_id, chat_id, checklist, + disable_notification=None, protect_content=None, message_effect_id=None, + reply_parameters=None, reply_markup=None +): + method_url = r'sendChecklist' + payload = {'chat_id': chat_id, 'checklist': checklist, 'business_connection_id': business_connection_id} + if disable_notification is not None: + payload['disable_notification'] = disable_notification + if protect_content is not None: + payload['protect_content'] = protect_content + if message_effect_id is not None: + payload['message_effect_id'] = message_effect_id + if reply_parameters is not None: + payload['reply_parameters'] = reply_parameters.to_json() + if reply_markup is not None: + payload['reply_markup'] = _convert_markup(reply_markup) + return await _process_request(token, method_url, params=payload) + + +async def edit_message_checklist( + token, business_connection_id, chat_id, message_id, checklist, + reply_markup=None +): + method_url = r'editMessageChecklist' + payload = {'chat_id': chat_id, 'message_id': message_id, 'checklist': checklist, 'business_connection_id': business_connection_id} + if reply_markup is not None: + payload['reply_markup'] = await _convert_markup(reply_markup) + return await _process_request(token, method_url, params=payload) async def send_dice( token, chat_id, @@ -1816,6 +1845,11 @@ async def answer_pre_checkout_query(token, pre_checkout_query_id, ok, error_mess payload['error_message'] = error_message return await _process_request(token, method_url, params=payload) + +async def get_my_star_balance(token): + method_url = 'getMyStarBalance' + return await _process_request(token, method_url) + async def get_star_transactions(token, offset=None, limit=None): method_url = 'getStarTransactions' payload = {} diff --git a/telebot/types.py b/telebot/types.py index 513921fbd..8cc573246 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1049,6 +1049,9 @@ class Message(JsonDeserializable): :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation :type has_media_spoiler: :obj:`bool` + :param checklist: Optional. Message is a checklist + :type checklist: :class:`telebot.types.Checklist` + :param contact: Optional. Message is a shared contact, information about the contact :type contact: :class:`telebot.types.Contact` @@ -1161,6 +1164,15 @@ class Message(JsonDeserializable): :param chat_background_set: Optional. Service message: chat background set :type chat_background_set: :class:`telebot.types.ChatBackground` + :param checklist_tasks_done: Optional. Service message: some tasks in a checklist were marked as done or not done + :type checklist_tasks_done: :class:`telebot.types.ChecklistTasksDone` + + :param checklist_tasks_added: Optional. Service message: tasks were added to a checklist + :type checklist_tasks_added: :class:`telebot.types.ChecklistTasksAdded` + + :param direct_message_price_changed: Optional. Service message: the price for paid messages in the corresponding direct messages chat of a channel has changed + :type direct_message_price_changed: :class:`telebot.types.DirectMessagePriceChanged` + :param forum_topic_created: Optional. Service message: forum topic created :type forum_topic_created: :class:`telebot.types.ForumTopicCreated` @@ -1461,8 +1473,18 @@ def de_json(cls, json_string): content_type = 'paid_message_price_changed' if 'paid_star_count' in obj: opts['paid_star_count'] = obj['paid_star_count'] + if 'checklist' in obj: + opts['checklist'] = Checklist.de_json(obj['checklist']) + if 'checklist_tasks_done' in obj: + opts['checklist_tasks_done'] = ChecklistTasksDone.de_json(obj['checklist_tasks_done']) + content_type = 'checklist_tasks_done' + if 'checklist_tasks_added' in obj: + opts['checklist_tasks_added'] = ChecklistTasksAdded.de_json(obj['checklist_tasks_added']) + content_type = 'checklist_tasks_added' + if 'direct_message_price_changed' in obj: + opts['direct_message_price_changed'] = DirectMessagePriceChanged.de_json(obj['direct_message_price_changed']) + content_type = 'direct_message_price_changed' - return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod @@ -1584,7 +1606,10 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.unique_gift : Optional[UniqueGiftInfo] = None self.paid_message_price_changed: Optional[PaidMessagePriceChanged] = None self.paid_star_count: Optional[int] = None - + self.checklist: Optional[Checklist] = None + self.checklist_tasks_done: Optional[ChecklistTasksDone] = None + self.checklist_tasks_added: Optional[List[ChecklistTasksAdded]] = None + self.direct_message_price_changed: Optional[DirectMessagePriceChanged] = None for key in options: setattr(self, key, options[key]) @@ -8786,6 +8811,9 @@ class ExternalReplyInfo(JsonDeserializable): :param has_media_spoiler: Optional. True, if the message media is covered by a spoiler animation :type has_media_spoiler: :obj:`bool` + :param checklist: Optional. Message is a checklist + :type checklist: :class:`telebot.types.Checklist` + :param contact: Optional. Message is a shared contact, information about the contact :type contact: :class:`Contact` @@ -8873,7 +8901,8 @@ def __init__( dice: Optional[Dice]=None, game: Optional[Game]=None, giveaway: Optional[Giveaway]=None, giveaway_winners: Optional[GiveawayWinners]=None, invoice: Optional[Invoice]=None, location: Optional[Location]=None, poll: Optional[Poll]=None, - venue: Optional[Venue]=None, paid_media: Optional[PaidMediaInfo]=None, **kwargs) -> None: + venue: Optional[Venue]=None, paid_media: Optional[PaidMediaInfo]=None, + checklist: Optional[Checklist]=None, **kwargs) -> None: self.origin: MessageOrigin = origin self.chat: Optional[Chat] = chat self.message_id: Optional[int] = message_id @@ -8898,6 +8927,7 @@ def __init__( self.poll: Optional[Poll] = poll self.venue: Optional[Venue] = venue self.paid_media: Optional[PaidMediaInfo] = paid_media + self.checklist: Optional[Checklist] = checklist # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -11623,11 +11653,14 @@ class OwnedGiftUnique(OwnedGift): :param transfer_star_count: Optional. Number of Telegram Stars that must be paid to transfer the gift; omitted if the bot cannot transfer the gift :type transfer_star_count: :obj:`int` + :param next_transfer_date: Optional. Point in time (Unix timestamp) when the gift can be transferred. If it is in the past, then the gift can be transferred now + :type next_transfer_date: :obj:`int` + :return: Instance of the class :rtype: :class:`OwnedGiftUnique` """ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=None, is_saved=None, - can_be_transferred=None, transfer_star_count=None, **kwargs): + can_be_transferred=None, transfer_star_count=None, next_transfer_date=None, **kwargs): super().__init__(type=type) self.gift: UniqueGift = gift self.owned_gift_id: Optional[str] = owned_gift_id @@ -11636,6 +11669,7 @@ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=N self.is_saved: Optional[bool] = is_saved self.can_be_transferred: Optional[bool] = can_be_transferred self.transfer_star_count: Optional[int] = transfer_star_count + self.next_transfer_date: Optional[int] = next_transfer_date @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12307,24 +12341,35 @@ class UniqueGiftInfo(JsonDeserializable): :param gift: Information about the gift :type gift: :class:`UniqueGift` - :param origin: Origin of the gift. Currently, either “upgrade” or “transfer” + :param origin: Origin of the gift. Currently, either “upgrade” for gifts upgraded from regular gifts, “transfer” for gifts transferred from other users or channels, + or “resale” for gifts bought from other users :type origin: :obj:`str` + :param last_resale_star_count: Optional. For gifts bought from other users, the price paid for the gift + :type last_resale_star_count: :obj:`int` + :param owned_gift_id: Optional. Unique identifier of the received gift for the bot; only present for gifts received on behalf of business accounts :type owned_gift_id: :obj:`str` :param transfer_star_count: Optional. Number of Telegram Stars that must be paid to transfer the gift; omitted if the bot cannot transfer the gift :type transfer_star_count: :obj:`int` + :param next_transfer_date: Optional. Point in time (Unix timestamp) when the gift can be transferred. If it is in the past, then the gift can be transferred now + :type next_transfer_date: :obj:`int` + :return: Instance of the class :rtype: :class:`UniqueGiftInfo` """ def __init__(self, gift: UniqueGift, origin: str, owned_gift_id: Optional[str] = None, - transfer_star_count: Optional[int] = None, **kwargs): + transfer_star_count: Optional[int] = None, next_transfer_date: Optional[int] = None, + last_resale_star_count: Optional[int] = None, **kwargs): self.gift: UniqueGift = gift self.origin: str = origin + self.last_resale_star_count: Optional[int] = last_resale_star_count self.owned_gift_id: Optional[str] = owned_gift_id self.transfer_star_count: Optional[int] = transfer_star_count + self.next_transfer_date: Optional[int] = next_transfer_date + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12438,3 +12483,276 @@ def to_dict(self): return data def convert_input_profile_photo(self): return self.to_json(), {self._animation_name: self.animation} + + +class ChecklistTask(JsonDeserializable): + """ + Describes a task in a checklist. + + Telegram documentation: https://core.telegram.org/bots/api#checklisttask + + :param id: Unique identifier of the task + :type id: :obj:`int` + + :param text: Text of the task + :type text: :obj:`str` + + :param text_entities: Optional. Special entities that appear in the task text + :type text_entities: :obj:`list` of :class:`MessageEntity` + + :param completed_by_user: Optional. User that completed the task; omitted if the task wasn't completed + :type completed_by_user: :class:`User` + + :param completion_date: Optional. Point in time (Unix timestamp) when the task was completed; 0 if the task wasn't completed + :type completion_date: :obj:`int` + + :return: Instance of the class + :rtype: :class:`ChecklistTask` + """ + def __init__(self, id: int, text: str, text_entities: Optional[List[MessageEntity]] = None, + completed_by_user: Optional[User] = None, + completion_date: Optional[int] = None, **kwargs): + self.id: int = id + self.text: str = text + self.text_entities: Optional[List[MessageEntity]] = text_entities + self.completed_by_user: Optional[User] = completed_by_user + self.completion_date: Optional[int] = completion_date + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'text_entities' in obj: + obj['text_entities'] = [MessageEntity.de_json(entity) for entity in obj['text_entities']] + if 'completed_by_user' in obj: + obj['completed_by_user'] = User.de_json(obj['completed_by_user']) + return cls(**obj) + +class Checklist(JsonDeserializable): + """ + Describes a checklist. + + Telegram documentation: https://core.telegram.org/bots/api#checklist + + :param title: Title of the checklist + :type title: :obj:`str` + + :param title_entities: Optional. Special entities that appear in the checklist title + :type title_entities: :obj:`list` of :class:`MessageEntity` + + :param tasks: List of tasks in the checklist + :type tasks: :obj:`list` of :class:`ChecklistTask` + + :param others_can_add_tasks: Optional. True, if users other than the creator of the list can add tasks to the list + :type others_can_add_tasks: :obj:`bool` + + :param others_can_mark_tasks_as_done: Optional. True, if users other than the creator of the list can mark tasks as done or not done in the list + :type others_can_mark_tasks_as_done: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`Checklist` + """ + def __init__(self, title: str, tasks: List[ChecklistTask], + title_entities: Optional[List[MessageEntity]] = None, + others_can_add_tasks: Optional[bool] = None, + others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): + self.title: str = title + self.title_entities: Optional[List[MessageEntity]] = title_entities + self.tasks: List[ChecklistTask] = tasks + self.others_can_add_tasks: Optional[bool] = others_can_add_tasks + self.others_can_mark_tasks_as_done: Optional[bool] = others_can_mark_tasks_as_done + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'title_entities' in obj: + obj['title_entities'] = [MessageEntity.de_json(entity) for entity in obj['title_entities']] + if 'tasks' in obj: + obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] + return cls(**obj) + +class InputChecklistTask(JsonSerializable): + """ + Describes a task to add to a checklist. + + Telegram documentation: https://core.telegram.org/bots/api#inputchecklisttask + + :param id: Unique identifier of the task; must be positive and unique among all task identifiers currently present in the checklist + :type id: :obj:`int` + + :param text: Text of the task; 1-100 characters after entities parsing + :type text: :obj:`str` + + :param parse_mode: Optional. Mode for parsing entities in the text. See formatting options for more details. + :type parse_mode: :obj:`str` + + :param text_entities: Optional. List of special entities that appear in the text, which can be specified instead of parse_mode. Currently, only bold, italic, underline, strikethrough, spoiler, and custom_emoji entities are allowed. + :type text_entities: :obj:`list` of :class:`MessageEntity` + + :return: Instance of the class + :rtype: :class:`InputChecklistTask` + """ + def __init__(self, id: int, text: str, parse_mode: Optional[str] = None, + text_entities: Optional[List[MessageEntity]] = None, **kwargs): + self.id: int = id + self.text: str = text + self.parse_mode: Optional[str] = parse_mode + self.text_entities: Optional[List[MessageEntity]] = text_entities + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'id': self.id, + 'text': self.text + } + if self.parse_mode is not None: + data['parse_mode'] = self.parse_mode + if self.text_entities is not None: + data['text_entities'] = [entity.to_dict() for entity in self.text_entities] + return data + +class InputChecklist(JsonSerializable): + """ + Describes a checklist to create. + + Telegram documentation: https://core.telegram.org/bots/api#inputchecklist + + :param title: Title of the checklist; 1-255 characters after entities parsing + :type title: :obj:`str` + + :param parse_mode: Optional. Mode for parsing entities in the title. See formatting options for more details. + :type parse_mode: :obj:`str` + + :param title_entities: Optional. List of special entities that appear in the title, which can be specified instead of parse_mode. Currently, only bold, italic, underline, strikethrough, spoiler, and custom_emoji entities are allowed. + :type title_entities: :obj:`list` of :class:`MessageEntity` + + :param tasks: List of 1-30 tasks in the checklist + :type tasks: :obj:`list` of :class:`InputChecklistTask` + + :param others_can_add_tasks: Optional. Pass True if other users can add tasks to the checklist + :type others_can_add_tasks: :obj:`bool` + + :param others_can_mark_tasks_as_done: Optional. Pass True if other users can mark tasks as done or not done in the checklist + :type others_can_mark_tasks_as_done: :obj:`bool` + + :return: Instance of the class + :rtype: :class:`InputChecklist` + """ + def __init__(self, title: str, tasks: List[InputChecklistTask], + parse_mode: Optional[str] = None, + title_entities: Optional[List[MessageEntity]] = None, + others_can_add_tasks: Optional[bool] = None, + others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): + self.title: str = title + self.parse_mode: Optional[str] = parse_mode + self.title_entities: Optional[List[MessageEntity]] = title_entities + self.tasks: List[InputChecklistTask] = tasks + self.others_can_add_tasks: Optional[bool] = others_can_add_tasks + self.others_can_mark_tasks_as_done: Optional[bool] = others_can_mark_tasks_as_done + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'title': self.title, + 'tasks': [task.to_dict() for task in self.tasks] + } + if self.parse_mode is not None: + data['parse_mode'] = self.parse_mode + if self.title_entities is not None: + data['title_entities'] = [entity.to_dict() for entity in self.title_entities] + if self.others_can_add_tasks is not None: + data['others_can_add_tasks'] = self.others_can_add_tasks + if self.others_can_mark_tasks_as_done is not None: + data['others_can_mark_tasks_as_done'] = self.others_can_mark_tasks_as_done + + +class ChecklistTasksDone(JsonDeserializable): + """ + Describes a service message about checklist tasks marked as done or not done. + + Telegram documentation: https://core.telegram.org/bots/api#checklisttasksdone + + :param checklist_message: Optional. Message containing the checklist whose tasks were marked as done or not done. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type checklist_message: :class:`Message` + + :param marked_as_done_task_ids: Optional. Identifiers of the tasks that were marked as done + :type marked_as_done_task_ids: :obj:`list` of :obj:`int + + :param marked_as_not_done_task_ids: Optional. Identifiers of the tasks that were marked as not done + :type marked_as_not_done_task_ids: :obj:`list` of :obj:`int` + + :return: Instance of the class + :rtype: :class:`ChecklistTasksDone` + """ + def __init__(self, checklist_message: Optional[Message] = None, + marked_as_done_task_ids: Optional[List[int]] = None, + marked_as_not_done_task_ids: Optional[List[int]] = None, **kwargs): + self.checklist_message: Optional[Message] = checklist_message + self.marked_as_done_task_ids: Optional[List[int]] = marked_as_done_task_ids + self.marked_as_not_done_task_ids: Optional[List[int]] = marked_as_not_done_task_ids + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'checklist_message' in obj: + obj['checklist_message'] = Message.de_json(obj['checklist_message']) + return cls(**obj) + + +class ChecklistTasksAdded(JsonDeserializable): + """ + Describes a service message about tasks added to a checklist. + + Telegram documentation: https://core.telegram.org/bots/api#checklisttasksadded + + :param checklist_message: Optional. Message containing the checklist to which the tasks were added. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type checklist_message: :class:`Message` + + :param tasks: List of tasks added to the checklist + :type tasks: :obj:`list` of :class:`ChecklistTask` + + :return: Instance of the class + :rtype: :class:`ChecklistTasksAdded` + """ + def __init__(self, tasks: List[ChecklistTask], checklist_message: Optional[Message] = None, **kwargs): + self.checklist_message: Optional[Message] = checklist_message + self.tasks: List[ChecklistTask] = tasks + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'checklist_message' in obj: + obj['checklist_message'] = Message.de_json(obj['checklist_message']) + obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] + return cls(**obj) + +class DirectMessagePriceChanged(JsonDeserializable): + """ + Describes a service message about a change in the price of direct messages sent to a channel chat. + + Telegram documentation: https://core.telegram.org/bots/api#directmessagepricechanged + + :param are_direct_messages_enabled: True, if direct messages are enabled for the channel chat; false otherwise + :type are_direct_messages_enabled: :obj:`bool` + + :param direct_message_star_count: Optional. The new number of Telegram Stars that must be paid by users for each direct message sent to the channel. Does not apply to users who have been exempted by administrators. Defaults to 0. + :type direct_message_star_count: :obj:`int` + + :return: Instance of the class + :rtype: :class:`DirectMessagePriceChanged` + """ + def __init__(self, are_direct_messages_enabled: bool, direct_message_star_count: Optional[int] = None, **kwargs): + self.are_direct_messages_enabled: bool = are_direct_messages_enabled + self.direct_message_star_count: Optional[int] = direct_message_star_count + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) From b9f0f9a3c7a9e50ed717c002726a7cc9c432a9d0 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 4 Jul 2025 21:44:04 +0500 Subject: [PATCH 445/480] Fix test error --- telebot/apihelper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 634b805d3..d3eb9c6b6 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -500,7 +500,7 @@ def edit_message_checklist( method_url = r'editMessageChecklist' payload = {'chat_id': chat_id, 'message_id': message_id, 'checklist': checklist, 'business_connection_id': business_connection_id} if reply_markup is not None: - payload['reply_markup'] = await _convert_markup(reply_markup) + payload['reply_markup'] = _convert_markup(reply_markup) return _make_request(token, method_url, params=payload) From 2621a56a0e4e0568ab44e8976e5279bd5aba9142 Mon Sep 17 00:00:00 2001 From: _run Date: Fri, 4 Jul 2025 21:48:16 +0500 Subject: [PATCH 446/480] Add new util service messages --- telebot/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telebot/util.py b/telebot/util.py index 8daf1d43c..05a7866f1 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -40,7 +40,8 @@ 'write_access_allowed', 'proximity_alert_triggered', 'forum_topic_created', 'forum_topic_edited', 'forum_topic_closed', 'forum_topic_reopened', 'general_forum_topic_hidden', 'general_forum_topic_unhidden', 'giveaway_created', 'giveaway', 'giveaway_winners', 'giveaway_completed', 'video_chat_scheduled', - 'video_chat_started', 'video_chat_ended', 'video_chat_participants_invited', + 'video_chat_started', 'video_chat_ended', 'video_chat_participants_invited','checklist_tasks_done', + 'checklist_tasks_added','direct_message_price_changed' ] #: All update types, should be used for allowed_updates parameter in polling. From f21e681dc833bb1cdcc84ec4d0c26612e600326f Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 6 Jul 2025 14:08:16 +0500 Subject: [PATCH 447/480] Fix inconsistent parts and bugs --- telebot/apihelper.py | 8 ++++---- telebot/asyncio_helper.py | 8 ++++---- telebot/types.py | 25 ++++++++++++++----------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index d3eb9c6b6..9318d926d 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -484,11 +484,11 @@ def send_checklist( payload['disable_notification'] = disable_notification if protect_content is not None: payload['protect_content'] = protect_content - if message_effect_id is not None: + if message_effect_id: payload['message_effect_id'] = message_effect_id - if reply_parameters is not None: + if reply_parameters: payload['reply_parameters'] = reply_parameters.to_json() - if reply_markup is not None: + if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) return _make_request(token, method_url, params=payload) @@ -499,7 +499,7 @@ def edit_message_checklist( ): method_url = r'editMessageChecklist' payload = {'chat_id': chat_id, 'message_id': message_id, 'checklist': checklist, 'business_connection_id': business_connection_id} - if reply_markup is not None: + if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) return _make_request(token, method_url, params=payload) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 4a542ffcf..bc50068f6 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -488,11 +488,11 @@ async def send_checklist( payload['disable_notification'] = disable_notification if protect_content is not None: payload['protect_content'] = protect_content - if message_effect_id is not None: + if message_effect_id: payload['message_effect_id'] = message_effect_id - if reply_parameters is not None: + if reply_parameters: payload['reply_parameters'] = reply_parameters.to_json() - if reply_markup is not None: + if reply_markup: payload['reply_markup'] = _convert_markup(reply_markup) return await _process_request(token, method_url, params=payload) @@ -503,7 +503,7 @@ async def edit_message_checklist( ): method_url = r'editMessageChecklist' payload = {'chat_id': chat_id, 'message_id': message_id, 'checklist': checklist, 'business_connection_id': business_connection_id} - if reply_markup is not None: + if reply_markup: payload['reply_markup'] = await _convert_markup(reply_markup) return await _process_request(token, method_url, params=payload) diff --git a/telebot/types.py b/telebot/types.py index 8cc573246..3f04a6d62 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -8889,6 +8889,10 @@ def de_json(cls, json_string): obj['poll'] = Poll.de_json(obj['poll']) if 'venue' in obj: obj['venue'] = Venue.de_json(obj['venue']) + if 'paid_media' in obj: + obj['paid_media'] = PaidMediaInfo.de_json(obj['paid_media']) + if 'checklist' in obj: + obj['checklist'] = Checklist.de_json(obj['checklist']) return cls(**obj) def __init__( @@ -12523,7 +12527,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'text_entities' in obj: - obj['text_entities'] = [MessageEntity.de_json(entity) for entity in obj['text_entities']] + obj['text_entities'] = Message.parse_entities(obj['text_entities']) if 'completed_by_user' in obj: obj['completed_by_user'] = User.de_json(obj['completed_by_user']) return cls(**obj) @@ -12552,8 +12556,8 @@ class Checklist(JsonDeserializable): :return: Instance of the class :rtype: :class:`Checklist` """ - def __init__(self, title: str, tasks: List[ChecklistTask], - title_entities: Optional[List[MessageEntity]] = None, + def __init__(self, title: str,title_entities: Optional[List[MessageEntity]] = None, + tasks: List[ChecklistTask] = None, others_can_add_tasks: Optional[bool] = None, others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): self.title: str = title @@ -12567,7 +12571,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) if 'title_entities' in obj: - obj['title_entities'] = [MessageEntity.de_json(entity) for entity in obj['title_entities']] + obj['title_entities'] = Message.parse_entities(obj['title_entities']) if 'tasks' in obj: obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] return cls(**obj) @@ -12608,9 +12612,9 @@ def to_dict(self): 'id': self.id, 'text': self.text } - if self.parse_mode is not None: + if self.parse_mode: data['parse_mode'] = self.parse_mode - if self.text_entities is not None: + if self.text_entities: data['text_entities'] = [entity.to_dict() for entity in self.text_entities] return data @@ -12641,10 +12645,9 @@ class InputChecklist(JsonSerializable): :return: Instance of the class :rtype: :class:`InputChecklist` """ - def __init__(self, title: str, tasks: List[InputChecklistTask], - parse_mode: Optional[str] = None, + def __init__(self, title: str,parse_mode: Optional[str] = None, title_entities: Optional[List[MessageEntity]] = None, - others_can_add_tasks: Optional[bool] = None, + tasks: List[InputChecklistTask], others_can_add_tasks: Optional[bool] = None, others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): self.title: str = title self.parse_mode: Optional[str] = parse_mode @@ -12661,9 +12664,9 @@ def to_dict(self): 'title': self.title, 'tasks': [task.to_dict() for task in self.tasks] } - if self.parse_mode is not None: + if self.parse_mode: data['parse_mode'] = self.parse_mode - if self.title_entities is not None: + if self.title_entities: data['title_entities'] = [entity.to_dict() for entity in self.title_entities] if self.others_can_add_tasks is not None: data['others_can_add_tasks'] = self.others_can_add_tasks From 7a8d76c045bc60be58f9ce1addb4b11b2c918dd9 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 6 Jul 2025 14:17:48 +0500 Subject: [PATCH 448/480] Fix the test --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 3f04a6d62..26be8ed16 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -12647,7 +12647,7 @@ class InputChecklist(JsonSerializable): """ def __init__(self, title: str,parse_mode: Optional[str] = None, title_entities: Optional[List[MessageEntity]] = None, - tasks: List[InputChecklistTask], others_can_add_tasks: Optional[bool] = None, + tasks: List[InputChecklistTask]=None, others_can_add_tasks: Optional[bool] = None, others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): self.title: str = title self.parse_mode: Optional[str] = parse_mode From 9980e6e6529a195567c2794f0182143f3c110597 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 6 Jul 2025 16:02:45 +0500 Subject: [PATCH 449/480] Parameter order fix --- telebot/types.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 26be8ed16..971f5824c 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -12556,13 +12556,13 @@ class Checklist(JsonDeserializable): :return: Instance of the class :rtype: :class:`Checklist` """ - def __init__(self, title: str,title_entities: Optional[List[MessageEntity]] = None, - tasks: List[ChecklistTask] = None, + def __init__(self, title: str, tasks: List[ChecklistTask], + title_entities: Optional[List[MessageEntity]] = None, others_can_add_tasks: Optional[bool] = None, others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): self.title: str = title - self.title_entities: Optional[List[MessageEntity]] = title_entities self.tasks: List[ChecklistTask] = tasks + self.title_entities: Optional[List[MessageEntity]] = title_entities self.others_can_add_tasks: Optional[bool] = others_can_add_tasks self.others_can_mark_tasks_as_done: Optional[bool] = others_can_mark_tasks_as_done @@ -12572,8 +12572,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'title_entities' in obj: obj['title_entities'] = Message.parse_entities(obj['title_entities']) - if 'tasks' in obj: - obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] + obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] return cls(**obj) class InputChecklistTask(JsonSerializable): @@ -12645,14 +12644,15 @@ class InputChecklist(JsonSerializable): :return: Instance of the class :rtype: :class:`InputChecklist` """ - def __init__(self, title: str,parse_mode: Optional[str] = None, + def __init__(self, title: str, tasks: List[InputChecklistTask], + parse_mode: Optional[str] = None, title_entities: Optional[List[MessageEntity]] = None, - tasks: List[InputChecklistTask]=None, others_can_add_tasks: Optional[bool] = None, + others_can_add_tasks: Optional[bool] = None, others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): self.title: str = title + self.tasks: List[InputChecklistTask] = tasks self.parse_mode: Optional[str] = parse_mode self.title_entities: Optional[List[MessageEntity]] = title_entities - self.tasks: List[InputChecklistTask] = tasks self.others_can_add_tasks: Optional[bool] = others_can_add_tasks self.others_can_mark_tasks_as_done: Optional[bool] = others_can_mark_tasks_as_done From 012eac4211f83a463bf96ce48bbd6cb73a11e5d8 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 26 Jul 2025 10:25:30 +0300 Subject: [PATCH 450/480] Bump version --- README.md | 2 +- docs/source/conf.py | 2 +- pyproject.toml | 5 ++--- telebot/version.py | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 262fc2beb..7a67b7d78 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

diff --git a/docs/source/conf.py b/docs/source/conf.py index 000225031..4dcffc212 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.27.0' +release = '4.28.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index e7bf04f85..d2db6d2b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.27.0" +version = "4.28.0" description = "Python Telegram bot api." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} @@ -22,7 +22,7 @@ classifiers = [ "Environment :: Console", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)" ] -dependencies = ["requests"] +dependencies = ["pytest", "requests", "wheel", "aiohttp"] [project.urls] Homepage = "https://github.com/eternnoir/pyTelegramBotAPI" @@ -35,7 +35,6 @@ Issues = "https://github.com/eternnoir/pyTelegramBotAPI/issues" json = ["ujson"] PIL = ["Pillow"] redis = ["redis>=3.4.1"] -aiohttp = ["aiohttp"] fastapi = ["fastapi"] uvicorn = ["uvicorn"] psutil = ["psutil"] diff --git a/telebot/version.py b/telebot/version.py index e0fe9ac48..c2bb2a64b 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.27.0' +__version__ = '4.28.0' From 86056efaa8777a2705c4d56fa53ca3a194aef472 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 07:29:07 +0000 Subject: [PATCH 451/480] Bump aiohttp from 3.10.11 to 3.12.14 --- updated-dependencies: - dependency-name: aiohttp dependency-version: 3.12.14 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index febcca257..ced176c9f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest requests==2.32.4 wheel==0.38.1 -aiohttp==3.10.11 +aiohttp==3.12.14 From 492919e213d79b14da4b9e1c68ca6741ceeb33db Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 26 Jul 2025 10:49:49 +0300 Subject: [PATCH 452/480] content_type_xxx aligned 1. content_type_media, content_type_service, update_types ordered according to presence in code to make add missing ones easier. 2. Added some missed content types. --- telebot/util.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/telebot/util.py b/telebot/util.py index 05a7866f1..2f92ae781 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -27,29 +27,30 @@ #: Contains all media content types. content_type_media = [ - 'text', 'animation', 'audio', 'document', 'photo', 'sticker', 'story', 'video', 'video_note', 'voice', 'contact', - 'dice', 'game', 'poll', 'venue', 'location', 'invoice', 'successful_payment', 'connected_website', - 'passport_data', 'web_app_data', + 'text', 'audio', 'document', 'animation', 'game', 'photo', 'sticker', 'video', 'video_note', 'voice', 'contact', + 'location', 'venue', 'dice', 'invoice', 'successful_payment', 'connected_website', 'poll', 'passport_data', + 'web_app_data', 'story', 'giveaway', 'gift', 'unique_gift', ] #: Contains all service content types such as `User joined the group`. content_type_service = [ 'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', - 'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'message_auto_delete_timer_changed', - 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message', 'users_shared', 'chat_shared', - 'write_access_allowed', 'proximity_alert_triggered', 'forum_topic_created', 'forum_topic_edited', - 'forum_topic_closed', 'forum_topic_reopened', 'general_forum_topic_hidden', 'general_forum_topic_unhidden', - 'giveaway_created', 'giveaway', 'giveaway_winners', 'giveaway_completed', 'video_chat_scheduled', - 'video_chat_started', 'video_chat_ended', 'video_chat_participants_invited','checklist_tasks_done', - 'checklist_tasks_added','direct_message_price_changed' + 'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id', + 'migrate_from_chat_id', 'pinned_message', 'proximity_alert_triggered', 'video_chat_scheduled', + 'video_chat_started', 'video_chat_ended', 'video_chat_participants_invited', 'message_auto_delete_timer_changed', + 'chat_background_set', 'forum_topic_created', 'forum_topic_closed', 'forum_topic_reopened', 'forum_topic_edited', + 'general_forum_topic_hidden', 'general_forum_topic_unhidden', 'write_access_allowed', 'users_shared', 'chat_shared', + 'giveaway_created', 'giveaway_winners', 'giveaway_completed', 'boost_added', 'paid_message_price_changed', + 'checklist_tasks_done', 'checklist_tasks_added', 'direct_message_price_changed', ] #: All update types, should be used for allowed_updates parameter in polling. update_types = [ "message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member", - "chat_join_request", "message_reaction", "message_reaction_count", "chat_boost", "removed_chat_boost", - "business_connection", "business_message", "edited_business_message", "deleted_business_messages", "purchased_paid_media" + "chat_join_request", "message_reaction", "message_reaction_count", "removed_chat_boost", "chat_boost", + "business_connection", "business_message", "edited_business_message", "deleted_business_messages", + "purchased_paid_media", ] From 6bc1c36251c83f0cfa606eb396a7bf7ad40fc6a2 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 26 Jul 2025 14:42:41 +0300 Subject: [PATCH 453/480] Some deprecation warnings, formal and typo fixes --- telebot/apihelper.py | 7 ++- telebot/types.py | 146 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 124 insertions(+), 29 deletions(-) diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 9318d926d..cba38bbdd 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -168,6 +168,8 @@ def _make_request(token, method_name, method='get', params=None, files=None): json_result = _check_result(method_name, result) if json_result: return json_result['result'] + else: + return None def _check_result(method_name, result): @@ -1139,8 +1141,10 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non def get_method_by_type(data_type): if data_type == 'document': return r'sendDocument' - if data_type == 'sticker': + elif data_type == 'sticker': return r'sendSticker' + else: + raise ValueError(f"Unsupported data type: {data_type}.") def ban_chat_member(token, chat_id, user_id, until_date=None, revoke_messages=None): @@ -2524,6 +2528,7 @@ def convert_input_media_array(array): for input_media in array: if isinstance(input_media, types.InputMedia) or isinstance(input_media, types.InputPaidMedia): media_dict = input_media.to_dict() + key = "x" # stub if media_dict['media'].startswith('attach://'): key = media_dict['media'].replace('attach://', '') files[key] = input_media.media diff --git a/telebot/types.py b/telebot/types.py index 971f5824c..4a58c2529 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -276,7 +276,6 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.purchased_paid_media: Optional[PaidMediaPurchased] = purchased_paid_media - class ChatMemberUpdated(JsonDeserializable): """ This object represents changes in the status of a chat member. @@ -403,6 +402,7 @@ def __init__(self, chat, from_user, user_chat_id, date, bio=None, invite_link=No self.invite_link: Optional[ChatInviteLink] = invite_link self.user_chat_id: int = user_chat_id + class WebhookInfo(JsonDeserializable): """ Describes the current status of a webhook. @@ -6790,6 +6790,10 @@ def __init__(self, type, media, caption=None, parse_mode=None, caption_entities= self._media_name = service_utils.generate_random_token() self._media_dic = 'attach://{0}'.format(self._media_name) + if self.__class__ is InputMedia: + # Make InputMedia as ABC some time... + log_deprecation_warning('The InputMedia class should not be instantiated directly. Use particular InputMediaXXX class instead') + def to_json(self): return json.dumps(self.to_dict()) @@ -8547,9 +8551,16 @@ def de_json(cls, json_string): elif obj['type'] == 'custom_emoji': del obj['type'] return ReactionTypeCustomEmoji(**obj) + elif obj['type'] == 'paid': + del obj['type'] + return ReactionTypePaid(**obj) + else: + raise ValueError(f"Unknown reaction type: {obj['type']}.") def __init__(self, type: str) -> None: self.type: str = type + if self.__class__ is ReactionType: + log_deprecation_warning('The ReactionType class should not be instantiated directly. Use particular ReactionTypeXXX class instead') def to_dict(self) -> dict: json_dict = { @@ -8935,7 +8946,7 @@ def __init__( # noinspection PyUnresolvedReferences,PyShadowingBuiltins -class MessageOrigin(JsonDeserializable): +class MessageOrigin(JsonDeserializable, ABC): """ This object describes the origin of a message. @@ -8979,6 +8990,8 @@ def de_json(cls, json_string): elif message_type == 'channel': chat = Chat.de_json(obj['chat']) return MessageOriginChannel(date=obj['date'], chat=chat, message_id=obj['message_id'], author_signature=obj.get('author_signature')) + else: + raise ValueError(f"Unknown message origin type: {message_type}.") def __init__(self, type: str, date: int) -> None: self.type: str = type @@ -10513,13 +10526,17 @@ def de_json(cls, json_string): return cls(**obj) -class TransactionPartner(JsonDeserializable): +class TransactionPartner(JsonDeserializable, ABC): # noinspection PyUnresolvedReferences """ This object describes the source of a transaction, or its recipient for outgoing transactions. Currently, it can be one of TransactionPartnerFragment TransactionPartnerUser TransactionPartnerOther + TransactionPartnerTelegramAds + TransactionPartnerTelegramApi + TransactionPartnerAffiliateProgram + TransactionPartnerChat Telegram documentation: https://core.telegram.org/bots/api#transactionpartner @@ -10548,6 +10565,8 @@ def de_json(cls, json_string): return TransactionPartnerOther.de_json(obj) elif obj["type"] == "chat": return TransactionPartnerChat.de_json(obj) + else: + raise ValueError(f"Unknown transaction partner type: {obj['type']}") # noinspection PyShadowingBuiltins @@ -10581,6 +10600,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class TransactionPartnerTelegramApi(TransactionPartner): """ Describes a transaction with payment for paid broadcasting. @@ -10796,7 +10816,7 @@ def __init__(self, transactions, **kwargs): self.transactions: List[StarTransaction] = transactions -class PaidMedia(JsonDeserializable): +class PaidMedia(JsonDeserializable, ABC): """ This object describes paid media. Currently, it can be one of @@ -10820,6 +10840,8 @@ def de_json(cls, json_string): return PaidMediaPhoto.de_json(obj) elif obj["type"] == "video": return PaidMediaVideo.de_json(obj) + else: + raise ValueError("Unknown type of PaidMedia: {0}".format(obj["type"])) # noinspection PyShadowingBuiltins @@ -10947,7 +10969,7 @@ def __init__(self, star_count, paid_media, **kwargs): # noinspection PyShadowingBuiltins -class InputPaidMedia(JsonSerializable): +class InputPaidMedia(Dictionaryable, JsonSerializable): """ This object describes the paid media to be sent. Currently, it can be one of InputPaidMediaPhoto @@ -10970,6 +10992,10 @@ def __init__(self, type: str, media: Union[str, InputFile], **kwargs): self._media_name = service_utils.generate_random_token() self._media_dic = 'attach://{0}'.format(self._media_name) + if self.__class__ is InputPaidMedia: + # Make InputPaidMedia as ABC some time... + log_deprecation_warning('The InputPaidMedia class should not be instantiated directly. Use particular InputPaidMediaXXX class instead') + def to_json(self): return json.dumps(self.to_dict()) @@ -10979,7 +11005,8 @@ def to_dict(self): 'media': self._media_dic } return data - + + class InputPaidMediaPhoto(InputPaidMedia): """ The paid media to send is a photo. @@ -11000,7 +11027,8 @@ class InputPaidMediaPhoto(InputPaidMedia): def __init__(self, media: Union[str, InputFile], **kwargs): super().__init__(type='photo', media=media) - + + class InputPaidMediaVideo(InputPaidMedia): """ The paid media to send is a video. @@ -11058,8 +11086,6 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[InputFile] self.cover: Optional[Union[str,InputFile]] = cover self.start_timestamp: Optional[int] = start_timestamp - - def to_dict(self): data = super().to_dict() if self.thumbnail: @@ -11078,6 +11104,7 @@ def to_dict(self): data['start_timestamp'] = self.start_timestamp return data + class RefundedPayment(JsonDeserializable): """ This object contains basic information about a refunded payment. @@ -11176,6 +11203,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class PreparedInlineMessage(JsonDeserializable): """ Describes an inline message to be sent by a user of a Mini App. @@ -11203,6 +11231,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class Gift(JsonDeserializable): """ This object represents a gift that can be sent by the bot. @@ -11245,7 +11274,8 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + + class Gifts(JsonDeserializable): """ This object represent a list of gifts. @@ -11270,6 +11300,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class TransactionPartnerAffiliateProgram(TransactionPartner): """ Describes the affiliate program that issued the affiliate commission received via this transaction. @@ -11347,6 +11378,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class TransactionPartnerChat(TransactionPartner): """ Describes a transaction with a chat. @@ -11497,6 +11529,7 @@ def to_dict(self): 'premium_subscription': self.premium_subscription } return data + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11522,13 +11555,15 @@ class StarAmount(JsonDeserializable): def __init__(self, amount, nanostar_amount=None, **kwargs): self.amount: int = amount self.nanostar_amount: Optional[int] = nanostar_amount + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + +# noinspection PyShadowingBuiltins class OwnedGift(JsonDeserializable, ABC): """ This object describes a gift received and owned by a user or a chat. Currently, it can be one of @@ -11540,9 +11575,8 @@ class OwnedGift(JsonDeserializable, ABC): def __init__(self, type, **kwargs): self.type: str = type - self.gift: Union[Gift, UniqueGift] = None - - + self.gift: Optional[Union[Gift, UniqueGift]] = None + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11551,7 +11585,11 @@ def de_json(cls, json_string): return OwnedGiftRegular.de_json(obj) elif obj["type"] == "unique": return OwnedGiftUnique.de_json(obj) - + else: + raise ValueError(f"Unknown gift type: {obj['type']}.") + + +# noinspection PyShadowingBuiltins class OwnedGiftRegular(OwnedGift): """ This object describes a regular gift owned by a user or a chat. @@ -11616,6 +11654,7 @@ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=N self.was_refunded: Optional[bool] = was_refunded self.convert_star_count: Optional[int] = convert_star_count self.prepaid_upgrade_star_count: Optional[int] = prepaid_upgrade_star_count + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11626,7 +11665,9 @@ def de_json(cls, json_string): if 'entities' in obj: obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] return cls(**obj) - + + +# noinspection PyShadowingBuiltins class OwnedGiftUnique(OwnedGift): """ This object describes a unique gift owned by a user or a chat. @@ -11674,6 +11715,7 @@ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=N self.can_be_transferred: Optional[bool] = can_be_transferred self.transfer_star_count: Optional[int] = transfer_star_count self.next_transfer_date: Optional[int] = next_transfer_date + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11707,6 +11749,7 @@ def __init__(self, total_count, gifts, next_offset=None, **kwargs): self.total_count: int = total_count self.gifts: List[OwnedGift] = gifts self.next_offset: Optional[str] = next_offset + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11715,7 +11758,6 @@ def de_json(cls, json_string): return cls(**obj) - class UniqueGift(JsonDeserializable): """ This object describes a unique gift that was upgraded from a regular gift. @@ -11750,6 +11792,7 @@ def __init__(self, base_name, name, number, model, symbol, backdrop, **kwargs): self.model: UniqueGiftModel = model self.symbol: UniqueGiftSymbol = symbol self.backdrop: UniqueGiftBackdrop = backdrop + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11783,13 +11826,15 @@ def __init__(self, name, sticker, rarity_per_mille, **kwargs): self.name: str = name self.sticker: Sticker = sticker self.rarity_per_mille: int = rarity_per_mille + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + + class UniqueGiftSymbol(JsonDeserializable): """ This object describes the symbol shown on the pattern of a unique gift. @@ -11813,13 +11858,15 @@ def __init__(self, name, sticker, rarity_per_mille, **kwargs): self.name: str = name self.sticker: Sticker = sticker self.rarity_per_mille: int = rarity_per_mille + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + + class UniqueGiftBackdropColors(JsonDeserializable): """ This object describes the colors of the backdrop of a unique gift. @@ -11846,12 +11893,14 @@ def __init__(self, center_color, edge_color, symbol_color, text_color, **kwargs) self.edge_color: int = edge_color self.symbol_color: int = symbol_color self.text_color: int = text_color + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + + class UniqueGiftBackdrop(JsonDeserializable): """ This object describes the backdrop of a unique gift. @@ -11874,6 +11923,7 @@ def __init__(self, name, colors, rarity_per_mille, **kwargs): self.name: str = name self.colors: UniqueGiftBackdropColors = colors self.rarity_per_mille: int = rarity_per_mille + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11881,6 +11931,8 @@ def de_json(cls, json_string): obj['colors'] = UniqueGiftBackdropColors.de_json(obj['colors']) return cls(**obj) + +# noinspection PyShadowingBuiltins class InputStoryContent(JsonSerializable, ABC): """ This object describes the content of a story to post. Currently, it can be one of @@ -11888,7 +11940,6 @@ class InputStoryContent(JsonSerializable, ABC): InputStoryContentVideo Telegram documentation: https://core.telegram.org/bots/api#inputstorycontent - """ def __init__(self, type: str, **kwargs): self.type: str = type @@ -11956,6 +12007,7 @@ def __init__(self, video: InputFile, duration: Optional[float] = None, cover_fra self.duration: Optional[float] = duration self.cover_frame_timestamp: Optional[float] = cover_frame_timestamp self.is_animation: Optional[bool] = is_animation + def to_json(self): return json.dumps(self.to_dict()) @@ -11971,6 +12023,7 @@ def to_dict(self): if self.is_animation is not None: data['is_animation'] = self.is_animation return data + def convert_input_story(self): return self.to_json(), {self._video_name: self.video} @@ -12010,8 +12063,10 @@ def __init__(self, x_percentage: float, y_percentage: float, width_percentage: f self.height_percentage: float = height_percentage self.rotation_angle: float = rotation_angle self.corner_radius_percentage: float = corner_radius_percentage + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'x_percentage': self.x_percentage, @@ -12051,8 +12106,10 @@ def __init__(self, country_code: str, state: Optional[str] = None, city: Optiona self.state: Optional[str] = state self.city: Optional[str] = city self.street: Optional[str] = street + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'country_code': self.country_code @@ -12064,7 +12121,9 @@ def to_dict(self): if self.street is not None: data['street'] = self.street return data + +# noinspection PyShadowingBuiltins class StoryAreaType(JsonSerializable, ABC): """ Describes the type of a clickable area on a story. Currently, it can be one of @@ -12109,8 +12168,10 @@ def __init__(self,latitude: float, longitude: float, address: LocationAddress = self.latitude: float = latitude self.longitude: float = longitude self.address: Optional[LocationAddress] = address + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12148,8 +12209,10 @@ def __init__(self, reaction_type: ReactionType, is_dark: Optional[bool] = None, self.reaction_type: ReactionType = reaction_type self.is_dark: Optional[bool] = is_dark self.is_flipped: Optional[bool] = is_flipped + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12160,7 +12223,8 @@ def to_dict(self): if self.is_flipped is not None: data['is_flipped'] = self.is_flipped return data - + + class StoryAreaTypeLink(StoryAreaType): """ Describes a story area pointing to an HTTP or tg:// link. Currently, a story can have up to 3 link areas. @@ -12179,15 +12243,18 @@ class StoryAreaTypeLink(StoryAreaType): def __init__(self, url: str, **kwargs): super().__init__(type="link") self.url: str = url + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, 'url': self.url } return data - + + class StoryAreaTypeWeather(StoryAreaType): """ Describes a story area containing weather information. Currently, a story can have up to 3 weather areas. @@ -12214,8 +12281,10 @@ def __init__(self, temperature: float, emoji: str, background_color: int, **kwar self.temperature: float = temperature self.emoji: str = emoji self.background_color: int = background_color + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12224,7 +12293,8 @@ def to_dict(self): 'background_color': self.background_color } return data - + + class StoryAreaTypeUniqueGift(StoryAreaType): """ Describes a story area pointing to a unique gift. Currently, a story can have at most 1 unique gift area. @@ -12243,8 +12313,10 @@ class StoryAreaTypeUniqueGift(StoryAreaType): def __init__(self, name: str, **kwargs): super().__init__(type="unique_gift") self.name: str = name + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12254,6 +12326,7 @@ def to_dict(self): return data +# noinspection PyShadowingBuiltins class StoryArea(JsonSerializable): """ Describes a clickable area on a story media. @@ -12272,8 +12345,10 @@ class StoryArea(JsonSerializable): def __init__(self, position: StoryAreaPosition, type: StoryAreaType, **kwargs): self.position: StoryAreaPosition = position self.type: StoryAreaType = type + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'position': self.position.to_dict(), @@ -12327,6 +12402,7 @@ def __init__(self, gift: Gift, owned_gift_id: Optional[str] = None, convert_star self.text: Optional[str] = text self.entities: Optional[List[MessageEntity]] = entities self.is_private: Optional[bool] = is_private + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12335,7 +12411,8 @@ def de_json(cls, json_string): if 'entities' in obj: obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] return cls(**obj) - + + class UniqueGiftInfo(JsonDeserializable): """ This object describes a service message about a unique gift that was sent or received. @@ -12396,6 +12473,7 @@ class PaidMessagePriceChanged(JsonDeserializable): """ def __init__(self, paid_message_star_count: int, **kwargs): self.paid_message_star_count: int = paid_message_star_count + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12403,7 +12481,7 @@ def de_json(cls, json_string): return cls(**obj) -class InputProfilePhoto(JsonSerializable): +class InputProfilePhoto(JsonSerializable, ABC): """ This object describes a profile photo to set. Currently, it can be one of InputProfilePhotoStatic @@ -12415,6 +12493,7 @@ class InputProfilePhoto(JsonSerializable): :rtype: :class:`InputProfilePhoto` """ + class InputProfilePhotoStatic(InputProfilePhoto): """ This object describes a static profile photo to set. @@ -12434,9 +12513,9 @@ class InputProfilePhotoStatic(InputProfilePhoto): def __init__(self, photo: InputFile, **kwargs): self.type: str = "static" self.photo: InputFile = photo - self._photo_name = service_utils.generate_random_token() self._photo_dic = "attach://{}".format(self._photo_name) + def to_json(self): return json.dumps(self.to_dict()) @@ -12446,6 +12525,7 @@ def to_dict(self): 'photo': self._photo_dic } return data + def convert_input_profile_photo(self): return self.to_json(), {self._photo_name: self.photo} @@ -12475,8 +12555,10 @@ def __init__(self, animation: InputFile, main_frame_timestamp: Optional[float] = self._animation_name = service_utils.generate_random_token() self._animation_dic = "attach://{}".format(self._animation_name) self.main_frame_timestamp: Optional[float] = main_frame_timestamp + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12485,10 +12567,12 @@ def to_dict(self): if self.main_frame_timestamp is not None: data['main_frame_timestamp'] = self.main_frame_timestamp return data + def convert_input_profile_photo(self): return self.to_json(), {self._animation_name: self.animation} +# noinspection PyShadowingBuiltins class ChecklistTask(JsonDeserializable): """ Describes a task in a checklist. @@ -12531,6 +12615,7 @@ def de_json(cls, json_string): if 'completed_by_user' in obj: obj['completed_by_user'] = User.de_json(obj['completed_by_user']) return cls(**obj) + class Checklist(JsonDeserializable): """ @@ -12575,6 +12660,8 @@ def de_json(cls, json_string): obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] return cls(**obj) + +# noinspection PyShadowingBuiltins class InputChecklistTask(JsonSerializable): """ Describes a task to add to a checklist. @@ -12616,7 +12703,8 @@ def to_dict(self): if self.text_entities: data['text_entities'] = [entity.to_dict() for entity in self.text_entities] return data - + + class InputChecklist(JsonSerializable): """ Describes a checklist to create. @@ -12726,6 +12814,7 @@ class ChecklistTasksAdded(JsonDeserializable): def __init__(self, tasks: List[ChecklistTask], checklist_message: Optional[Message] = None, **kwargs): self.checklist_message: Optional[Message] = checklist_message self.tasks: List[ChecklistTask] = tasks + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12735,6 +12824,7 @@ def de_json(cls, json_string): obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] return cls(**obj) + class DirectMessagePriceChanged(JsonDeserializable): """ Describes a service message about a change in the price of direct messages sent to a channel chat. From 18c524f1fb8d0919fe98654e26d68c3a10807c46 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 26 Jul 2025 15:35:32 +0300 Subject: [PATCH 454/480] ChatMemberXXX classes redesigned --- telebot/types.py | 200 ++++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 98 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 4a58c2529..a707b72ba 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3251,7 +3251,7 @@ def __init__(self, small_file_id, small_file_unique_id, big_file_id, big_file_un self.big_file_unique_id: str = big_file_unique_id -class ChatMember(JsonDeserializable): +class ChatMember(JsonDeserializable, ABC): """ This object contains information about one member of a chat. Currently, the following 6 types of chat members are supported: @@ -3266,78 +3266,31 @@ class ChatMember(JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#chatmember """ + def __init__(self, user, status, **kwargs): + self.user: User = user + self.status: str = status + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) - member_type = obj['status'] + status = obj['status'] # Ordered according to estimated appearance frequency. - if member_type == "member": + if status == "member": return ChatMemberMember(**obj) - elif member_type == "left": + elif status == "left": return ChatMemberLeft(**obj) - elif member_type == "kicked": + elif status == "kicked": return ChatMemberBanned(**obj) - elif member_type == "restricted": + elif status == "restricted": return ChatMemberRestricted(**obj) - elif member_type == "administrator": + elif status == "administrator": return ChatMemberAdministrator(**obj) - elif member_type == "creator": + elif status == "creator": return ChatMemberOwner(**obj) else: - # Should not be here. For "if something happen" compatibility - return cls(**obj) - - def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_edited=None, - can_post_messages=None, can_edit_messages=None, can_delete_messages=None, - can_restrict_members=None, can_promote_members=None, can_change_info=None, - can_invite_users=None, can_pin_messages=None, is_member=None, - can_send_messages=None, can_send_audios=None, can_send_documents=None, - can_send_photos=None, can_send_videos=None, can_send_video_notes=None, - can_send_voice_notes=None, - can_send_polls=None, - can_send_other_messages=None, can_add_web_page_previews=None, - can_manage_chat=None, can_manage_video_chats=None, - until_date=None, can_manage_topics=None, - can_post_stories=None, can_edit_stories=None, can_delete_stories=None, - **kwargs): - self.user: User = user - self.status: str = status - self.custom_title: str = custom_title - self.is_anonymous: bool = is_anonymous - self.can_be_edited: bool = can_be_edited - self.can_post_messages: bool = can_post_messages - self.can_edit_messages: bool = can_edit_messages - self.can_delete_messages: bool = can_delete_messages - self.can_restrict_members: bool = can_restrict_members - self.can_promote_members: bool = can_promote_members - self.can_change_info: bool = can_change_info - self.can_invite_users: bool = can_invite_users - self.can_pin_messages: bool = can_pin_messages - self.is_member: bool = is_member - self.can_send_messages: bool = can_send_messages - self.can_send_polls: bool = can_send_polls - self.can_send_other_messages: bool = can_send_other_messages - self.can_add_web_page_previews: bool = can_add_web_page_previews - self.can_manage_chat: bool = can_manage_chat - self.can_manage_video_chats: bool = can_manage_video_chats - self.until_date: int = until_date - self.can_manage_topics: bool = can_manage_topics - self.can_send_audios: bool = can_send_audios - self.can_send_documents: bool = can_send_documents - self.can_send_photos: bool = can_send_photos - self.can_send_videos: bool = can_send_videos - self.can_send_video_notes: bool = can_send_video_notes - self.can_send_voice_notes: bool = can_send_voice_notes - self.can_post_stories: bool = can_post_stories - self.can_edit_stories: bool = can_edit_stories - self.can_delete_stories: bool = can_delete_stories - - @property - def can_manage_voice_chats(self): - log_deprecation_warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') - return self.can_manage_video_chats + raise ValueError(f"Unknown chat member type: {status}.") # noinspection PyUnresolvedReferences @@ -3362,7 +3315,10 @@ class ChatMemberOwner(ChatMember): :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberOwner` """ - pass + def __init__(self, user, status, is_anonymous, custom_title=None, **kwargs): + super().__init__(user, status, **kwargs) + self.is_anonymous: bool = is_anonymous + self.custom_title: Optional[str] = custom_title # noinspection PyUnresolvedReferences @@ -3409,36 +3365,60 @@ class ChatMemberAdministrator(ChatMember): :param can_invite_users: True, if the user is allowed to invite new users to the chat :type can_invite_users: :obj:`bool` + :param can_post_stories: True, if the administrator can post channel stories + :type can_post_stories: :obj:`bool` + + :param can_edit_stories: True, if the administrator can edit stories + :type can_edit_stories: :obj:`bool` + + :param can_delete_stories: True, if the administrator can delete stories of other users + :type can_delete_stories: :obj:`bool` + :param can_post_messages: Optional. True, if the administrator can post in the channel; channels only :type can_post_messages: :obj:`bool` - :param can_edit_messages: Optional. True, if the administrator can edit messages of other users and can pin - messages; channels only + :param can_edit_messages: Optional. True, if the administrator can edit messages of other users and can pin messages; channels only :type can_edit_messages: :obj:`bool` :param can_pin_messages: Optional. True, if the user is allowed to pin messages; groups and supergroups only :type can_pin_messages: :obj:`bool` - :param can_manage_topics: Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; - supergroups only + :param can_manage_topics: Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only :type can_manage_topics: :obj:`bool` :param custom_title: Optional. Custom title for this user :type custom_title: :obj:`str` - :param can_post_stories: Optional. True, if the administrator can post channel stories - :type can_post_stories: :obj:`bool` - - :param can_edit_stories: Optional. True, if the administrator can edit stories - :type can_edit_stories: :obj:`bool` - - :param can_delete_stories: Optional. True, if the administrator can delete stories of other users - :type can_delete_stories: :obj:`bool` - :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberAdministrator` """ - pass + def __init__(self, user, status, can_be_edited, is_anonymous, can_manage_chat, can_delete_messages, + can_manage_video_chats, can_restrict_members, can_promote_members, can_change_info, can_invite_users, + can_post_stories, can_edit_stories, can_delete_stories, can_post_messages=None, can_edit_messages=None, + can_pin_messages=None, can_manage_topics=None, custom_title=None, **kwargs): + super().__init__(user, status, **kwargs) + self.can_be_edited: bool = can_be_edited + self.is_anonymous: bool = is_anonymous + self.can_manage_chat: bool = can_manage_chat + self.can_delete_messages: bool = can_delete_messages + self.can_manage_video_chats: bool = can_manage_video_chats + self.can_restrict_members: bool = can_restrict_members + self.can_promote_members: bool = can_promote_members + self.can_change_info: bool = can_change_info + self.can_invite_users: bool = can_invite_users + self.can_post_stories: bool = can_post_stories + self.can_edit_stories: bool = can_edit_stories + self.can_delete_stories: bool = can_delete_stories + self.can_post_messages: Optional[bool] = can_post_messages + self.can_edit_messages: Optional[bool] = can_edit_messages + self.can_pin_messages: Optional[bool] = can_pin_messages + self.can_manage_topics: Optional[bool] = can_manage_topics + self.custom_title: Optional[str] = custom_title + + @property + def can_manage_voice_chats(self): + log_deprecation_warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') + return self.can_manage_video_chats # noinspection PyUnresolvedReferences @@ -3454,10 +3434,15 @@ class ChatMemberMember(ChatMember): :param user: Information about the user :type user: :class:`telebot.types.User` + :param until_date: Optional. Date when the user's subscription will expire; Unix time. If 0, then the user is a member forever + :type until_date: :obj:`int` + :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberMember` """ - pass + def __init__(self, user, status, until_date=None, **kwargs): + super().__init__(user, status, **kwargs) + self.until_date: Optional[int] = until_date # noinspection PyUnresolvedReferences @@ -3476,18 +3461,6 @@ class ChatMemberRestricted(ChatMember): :param is_member: True, if the user is a member of the chat at the moment of the request :type is_member: :obj:`bool` - :param can_change_info: True, if the user is allowed to change the chat title, photo and other settings - :type can_change_info: :obj:`bool` - - :param can_invite_users: True, if the user is allowed to invite new users to the chat - :type can_invite_users: :obj:`bool` - - :param can_pin_messages: True, if the user is allowed to pin messages - :type can_pin_messages: :obj:`bool` - - :param can_manage_topics: True, if the user is allowed to create forum topics - :type can_manage_topics: :obj:`bool` - :param can_send_messages: True, if the user is allowed to send text messages, contacts, locations and venues :type can_send_messages: :obj:`bool` @@ -3512,21 +3485,52 @@ class ChatMemberRestricted(ChatMember): :param can_send_polls: True, if the user is allowed to send polls :type can_send_polls: :obj:`bool` - :param can_send_other_messages: True, if the user is allowed to send animations, games, stickers and use inline - bots + :param can_send_other_messages: True, if the user is allowed to send animations, games, stickers and use inline bots :type can_send_other_messages: :obj:`bool` :param can_add_web_page_previews: True, if the user is allowed to add web page previews to their messages :type can_add_web_page_previews: :obj:`bool` - :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted - forever + :param can_change_info: True, if the user is allowed to change the chat title, photo and other settings + :type can_change_info: :obj:`bool` + + :param can_invite_users: True, if the user is allowed to invite new users to the chat + :type can_invite_users: :obj:`bool` + + :param can_pin_messages: True, if the user is allowed to pin messages + :type can_pin_messages: :obj:`bool` + + :param can_manage_topics: True, if the user is allowed to create forum topics + :type can_manage_topics: :obj:`bool` + + :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted forever :type until_date: :obj:`int` :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberRestricted` """ - pass + def __init__(self, user, status, is_member, can_send_messages, can_send_audios, can_send_documents, + can_send_photos, can_send_videos, can_send_video_notes, can_send_voice_notes, can_send_polls, + can_send_other_messages, can_add_web_page_previews, + can_change_info, can_invite_users, can_pin_messages, can_manage_topics, + until_date=None, **kwargs): + super().__init__(user, status, **kwargs) + self.is_member: bool = is_member + self.can_send_messages: bool = can_send_messages + self.can_send_audios: bool = can_send_audios + self.can_send_documents: bool = can_send_documents + self.can_send_photos: bool = can_send_photos + self.can_send_videos: bool = can_send_videos + self.can_send_video_notes: bool = can_send_video_notes + self.can_send_voice_notes: bool = can_send_voice_notes + self.can_send_polls: bool = can_send_polls + self.can_send_other_messages: bool = can_send_other_messages + self.can_add_web_page_previews: bool = can_add_web_page_previews + self.can_change_info: bool = can_change_info + self.can_invite_users: bool = can_invite_users + self.can_pin_messages: bool = can_pin_messages + self.can_manage_topics: bool = can_manage_topics + self.until_date: Optional[int] = until_date # noinspection PyUnresolvedReferences @@ -3561,14 +3565,15 @@ class ChatMemberBanned(ChatMember): :param user: Information about the user :type user: :class:`telebot.types.User` - :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is banned - forever + :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is banned forever :type until_date: :obj:`int` :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberBanned` """ - pass + def __init__(self, user, status, until_date=None, **kwargs): + super().__init__(user, status, **kwargs) + self.until_date: Optional[int] = until_date class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): @@ -3577,8 +3582,7 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): Telegram Documentation: https://core.telegram.org/bots/api#chatpermissions - :param can_send_messages: Optional. True, if the user is allowed to send text messages, contacts, locations and - venues + :param can_send_messages: Optional. True, if the user is allowed to send text messages, contacts, locations and venues :type can_send_messages: :obj:`bool` :param can_send_audios: Optional. True, if the user is allowed to send audios From 9dfb79661f735ca757f1d11bc2435e94ef581595 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 26 Jul 2025 15:41:20 +0300 Subject: [PATCH 455/480] Update test_chat_member_updated with appropriate params --- tests/test_types.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_types.py b/tests/test_types.py index 197834748..de01b0e5c 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -242,7 +242,7 @@ def test_json_chat_invite_link(): def test_chat_member_updated(): - json_string = r'{"chat": {"id": -1234567890123, "type": "supergroup", "title": "No Real Group", "username": "NoRealGroup"}, "from": {"id": 133869498, "is_bot": false, "first_name": "Vincent"}, "date": 1624119999, "old_chat_member": {"user": {"id": 77777777, "is_bot": false, "first_name": "Pepe"}, "status": "member"}, "new_chat_member": {"user": {"id": 77777777, "is_bot": false, "first_name": "Pepe"}, "status": "administrator"}}' + json_string = r'{"chat": {"id": -1234567890123, "type": "supergroup", "title": "No Real Group", "username": "NoRealGroup"}, "from": {"id": 133869498, "is_bot": false, "first_name": "Vincent"}, "date": 1624119999, "old_chat_member": {"user": {"id": 77777777, "is_bot": false, "first_name": "Pepe"}, "status": "member"}, "new_chat_member": {"user": {"id": 77777777, "is_bot": false, "first_name": "Pepe"}, "status": "left"}}' cm_updated = types.ChatMemberUpdated.de_json(json_string) assert cm_updated.chat.id == -1234567890123 assert cm_updated.from_user.id == 133869498 @@ -309,5 +309,3 @@ def test_message_entity(): sample_string_7 = r'{"update_id":934522167,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"reply_to_message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en"},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1712765863,"text":"text @UserName b i s u c p #hashtag https://example.com","entities":[{"offset":5,"length":9,"type":"mention"},{"offset":15,"length":1,"type":"bold"},{"offset":17,"length":1,"type":"italic"},{"offset":19,"length":1,"type":"strikethrough"},{"offset":21,"length":1,"type":"underline"},{"offset":23,"length":1,"type":"code"},{"offset":25,"length":1,"type":"spoiler"},{"offset":27,"length":8,"type":"hashtag"},{"offset":36,"length":19,"type":"url"}],"link_preview_options":{"is_disabled":true}},"quote":{"text":"text @UserName b i s u c p #hashtag https://example.com","entities":[{"offset":15,"length":1,"type":"bold"},{"offset":17,"length":1,"type":"italic"},{"offset":19,"length":1,"type":"strikethrough"},{"offset":21,"length":1,"type":"underline"},{"offset":25,"length":1,"type":"spoiler"}],"position":0,"is_manual":true},"text":"quote reply"}}' message_7 = types.Update.de_json(sample_string_7).message assert message_7.quote.html_text == 'text @UserName b i s u c p #hashtag https://example.com' - - From c01b90452b9fa1df554709e6efad116db41ef9c2 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 26 Jul 2025 15:42:29 +0300 Subject: [PATCH 456/480] Update test_chat_member_updated with appropriate params --- tests/test_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_types.py b/tests/test_types.py index de01b0e5c..630ab658c 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -248,7 +248,7 @@ def test_chat_member_updated(): assert cm_updated.from_user.id == 133869498 assert cm_updated.date == 1624119999 assert cm_updated.old_chat_member.status == "member" - assert cm_updated.new_chat_member.status == "administrator" + assert cm_updated.new_chat_member.status == "left" def test_webhook_info(): From 2a2adbcf753aa6b64b23ab49b1cf3b3b0e70d3e1 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Fri, 1 Aug 2025 14:19:22 +0300 Subject: [PATCH 457/480] Rollback changes in dependencies. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d2db6d2b5..c46727508 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers = [ "Environment :: Console", "License :: OSI Approved :: GNU General Public License v2 (GPLv2)" ] -dependencies = ["pytest", "requests", "wheel", "aiohttp"] +dependencies = ["requests"] [project.urls] Homepage = "https://github.com/eternnoir/pyTelegramBotAPI" From 9a58fdad5a669d7e049e8ca359820aee3fe29715 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 21:08:36 +0500 Subject: [PATCH 458/480] Added reply_to_checklist_task_id and checklist_task_id --- telebot/types.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index a707b72ba..68fe8ab36 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -968,6 +968,9 @@ class Message(JsonDeserializable): :param reply_to_story: Optional. For replies to a story, the original story :type reply_to_story: :class:`telebot.types.Story` + :param reply_to_checklist_task_id: Optional. Identifier of the specific checklist task that is being replied to + :type reply_to_checklist_task_id: :obj:`str` + :param via_bot: Optional. Bot through which the message was sent :type via_bot: :class:`telebot.types.User` @@ -1484,6 +1487,8 @@ def de_json(cls, json_string): if 'direct_message_price_changed' in obj: opts['direct_message_price_changed'] = DirectMessagePriceChanged.de_json(obj['direct_message_price_changed']) content_type = 'direct_message_price_changed' + if 'reply_to_checklist_task_id' in obj: + opts['reply_to_checklist_task_id'] = obj['reply_to_checklist_task_id'] return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1610,6 +1615,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.checklist_tasks_done: Optional[ChecklistTasksDone] = None self.checklist_tasks_added: Optional[List[ChecklistTasksAdded]] = None self.direct_message_price_changed: Optional[DirectMessagePriceChanged] = None + self.reply_to_checklist_task_id: Optional[int] = None for key in options: setattr(self, key, options[key]) @@ -9390,6 +9396,9 @@ class ReplyParameters(JsonDeserializable, Dictionaryable, JsonSerializable): :param quote_position: Optional. Position of the quote in the original message in UTF-16 code units :type quote_position: :obj:`int` + :param checklist_task_id: Optional. Optional. Identifier of the specific checklist task to be replied to + :type checklist_task_id: :obj:`int` + :return: Instance of the class :rtype: :class:`ReplyParameters` """ @@ -9405,7 +9414,7 @@ def de_json(cls, json_string): def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, allow_sending_without_reply: Optional[bool] = None, quote: Optional[str] = None, quote_parse_mode: Optional[str] = None, quote_entities: Optional[List[MessageEntity]] = None, - quote_position: Optional[int] = None, **kwargs) -> None: + quote_position: Optional[int] = None, checklist_task_id: Optional[int] = None, **kwargs) -> None: self.message_id: int = message_id self.chat_id: Optional[Union[int, str]] = chat_id self.allow_sending_without_reply: Optional[bool] = allow_sending_without_reply @@ -9413,6 +9422,7 @@ def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, self.quote_parse_mode: Optional[str] = quote_parse_mode self.quote_entities: Optional[List[MessageEntity]] = quote_entities self.quote_position: Optional[int] = quote_position + self.checklist_task_id: Optional[int] = checklist_task_id def to_dict(self) -> dict: json_dict = { @@ -9430,6 +9440,8 @@ def to_dict(self) -> dict: json_dict['quote_entities'] = [entity.to_dict() for entity in self.quote_entities] if self.quote_position is not None: json_dict['quote_position'] = self.quote_position + if self.checklist_task_id is not None: + json_dict['checklist_task_id'] = self.checklist_task_id return json_dict def to_json(self) -> str: From 54b41ed5fa0e233499cd919a1254d29d9b79febf Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 21:13:18 +0500 Subject: [PATCH 459/480] Added the field publisher_chat to the classes Gift and UniqueGift which can be used to get information about the chat that published a gift. --- telebot/types.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 68fe8ab36..5a317d7ba 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -11272,23 +11272,30 @@ class Gift(JsonDeserializable): :param remaining_count: Optional. The number of remaining gifts of this type that can be sent; for limited gifts only :type remaining_count: :obj:`int` + :param publisher_chat: Optional. Information about the chat that published the gift + :type publisher_chat: :class:`Chat` + :return: Instance of the class :rtype: :class:`Gift` """ - def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, upgrade_star_count=None, **kwargs): + def __init__(self, id, sticker, star_count, total_count=None, remaining_count=None, upgrade_star_count=None, + publisher_chat=None, **kwargs): self.id: str = id self.sticker: Sticker = sticker self.star_count: int = star_count self.total_count: Optional[int] = total_count self.remaining_count: Optional[int] = remaining_count self.upgrade_star_count: Optional[int] = upgrade_star_count + self.publisher_chat: Optional[Chat] = publisher_chat @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) + if 'publisher_chat' in obj: + obj['publisher_chat'] = Chat.de_json(obj['publisher_chat']) return cls(**obj) @@ -11798,16 +11805,20 @@ class UniqueGift(JsonDeserializable): :param backdrop: Backdrop of the gift :type backdrop: :class:`UniqueGiftBackdrop` + :param publisher_chat: Optional. Information about the chat that published the gift + :type publisher_chat: :class:`Chat` + :return: Instance of the class :rtype: :class:`UniqueGift` """ - def __init__(self, base_name, name, number, model, symbol, backdrop, **kwargs): + def __init__(self, base_name, name, number, model, symbol, backdrop, publisher_chat=None, **kwargs): self.base_name: str = base_name self.name: str = name self.number: int = number self.model: UniqueGiftModel = model self.symbol: UniqueGiftSymbol = symbol self.backdrop: UniqueGiftBackdrop = backdrop + self.publisher_chat: Optional[Chat] = publisher_chat @classmethod def de_json(cls, json_string): @@ -11816,6 +11827,8 @@ def de_json(cls, json_string): obj['model'] = UniqueGiftModel.de_json(obj['model']) obj['symbol'] = UniqueGiftSymbol.de_json(obj['symbol']) obj['backdrop'] = UniqueGiftBackdrop.de_json(obj['backdrop']) + if 'publisher_chat' in obj: + obj['publisher_chat'] = Chat.de_json(obj['publisher_chat']) return cls(**obj) From c29dd9aada733730c4970e67d7ec29d497f4681a Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 21:16:03 +0500 Subject: [PATCH 460/480] Added the field is_direct_messages to the classes Chat and ChatFullInfo which can be used to identify supergroups that are used as channel direct messages chats. --- telebot/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 5a317d7ba..fad52a60a 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -615,6 +615,9 @@ class ChatFullInfo(JsonDeserializable): :param is_forum: Optional. True, if the supergroup chat is a forum (has topics enabled) :type is_forum: :obj:`bool` + :param is_direct_messages: Optional. True, if the chat is the direct messages chat of a channel + :type is_direct_messages: :obj:`bool` + :param max_reaction_count: Optional. The maximum number of reactions that can be set on a message in the chat :type max_reaction_count: :obj:`int` @@ -783,7 +786,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, business_opening_hours=None, personal_chat=None, birthdate=None, can_send_paid_media=None, - accepted_gift_types=None, **kwargs): + accepted_gift_types=None, is_direct_messages=None, **kwargs): self.id: int = id self.type: str = type self.title: Optional[str] = title @@ -829,6 +832,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.birthdate: Optional[Birthdate] = birthdate self.can_send_paid_media: Optional[bool] = can_send_paid_media self.accepted_gift_types: AcceptedGiftTypes = accepted_gift_types + self.is_direct_messages: Optional[bool] = is_direct_messages @property def can_send_gift(self) -> bool: """ From a848089eef610c22ef13db8a5097e6f27425f8f5 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 21:17:46 +0500 Subject: [PATCH 461/480] Added the field parent_chat to the class ChatFullInfo which indicates the parent channel chat for a channel direct messages chat. --- telebot/types.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index fad52a60a..acd0c2cc1 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -642,6 +642,9 @@ class ChatFullInfo(JsonDeserializable): :param personal_chat: Optional. For private chats, the personal channel of the user. Returned only in getChat. :type personal_chat: :class:`telebot.types.Chat` + :param parent_chat: Optional. Information about the corresponding channel chat; for direct messages chats only + :type parent_chat: :class:`telebot.types.Chat` + :param available_reactions: Optional. List of available chat reactions; for private chats, supergroups and channels. Returned only in getChat. :type available_reactions: :obj:`list` of :class:`telebot.types.ReactionType` @@ -770,6 +773,8 @@ def de_json(cls, json_string): obj['birthdate'] = Birthdate.de_json(obj['birthdate']) if 'accepted_gift_types' in obj: obj['accepted_gift_types'] = AcceptedGiftTypes.de_json(obj['accepted_gift_types']) + if 'parent_chat' in obj: + obj['parent_chat'] = Chat.de_json(obj['parent_chat']) return cls(**obj) def __init__(self, id, type, title=None, username=None, first_name=None, @@ -786,7 +791,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, business_opening_hours=None, personal_chat=None, birthdate=None, can_send_paid_media=None, - accepted_gift_types=None, is_direct_messages=None, **kwargs): + accepted_gift_types=None, is_direct_messages=None, parent_chat=None, **kwargs): self.id: int = id self.type: str = type self.title: Optional[str] = title @@ -833,6 +838,7 @@ def __init__(self, id, type, title=None, username=None, first_name=None, self.can_send_paid_media: Optional[bool] = can_send_paid_media self.accepted_gift_types: AcceptedGiftTypes = accepted_gift_types self.is_direct_messages: Optional[bool] = is_direct_messages + self.parent_chat: Optional[Chat] = parent_chat @property def can_send_gift(self) -> bool: """ From 0df175748326cf509fb6e52abb18022d7a9923d6 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 21:20:56 +0500 Subject: [PATCH 462/480] Added the class DirectMessagesTopic and the field direct_messages_topic to the class Message, describing a topic of a direct messages chat. --- telebot/types.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index acd0c2cc1..b3958ac79 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -929,6 +929,9 @@ class Message(JsonDeserializable): :param message_thread_id: Optional. Unique identifier of a message thread to which the message belongs; for supergroups only :type message_thread_id: :obj:`int` + :param direct_messages_topic: Optional. Information about the direct messages chat topic that contains the message + :type direct_messages_topic: :class:`telebot.types.DirectMessagesTopic` + :param from_user: Optional. Sender of the message; empty for messages sent to channels. For backward compatibility, the field contains a fake sender user in non-channel chats, if the message was sent on behalf of a chat. :type from_user: :class:`telebot.types.User` @@ -1499,6 +1502,8 @@ def de_json(cls, json_string): content_type = 'direct_message_price_changed' if 'reply_to_checklist_task_id' in obj: opts['reply_to_checklist_task_id'] = obj['reply_to_checklist_task_id'] + if 'direct_messages_topic' in obj: + opts['direct_messages_topic'] = DirectMessagesTopic.de_json(obj['direct_messages_topic']) return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1626,6 +1631,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.checklist_tasks_added: Optional[List[ChecklistTasksAdded]] = None self.direct_message_price_changed: Optional[DirectMessagePriceChanged] = None self.reply_to_checklist_task_id: Optional[int] = None + self.direct_messages_topic: Optional[DirectMessagesTopic] = None for key in options: setattr(self, key, options[key]) @@ -12888,3 +12894,32 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) + + +class DirectMessagesTopic(JsonDeserializable): + """ + Describes a topic of a direct messages chat. + + Telegram documentation: https://core.telegram.org/bots/api#directmessagestopic + + :param topic_id: Unique identifier of the topic + :type topic_id: :obj:`int` + + :param user: Optional. Information about the user that created the topic. Currently, it is always present + :type user: :class:`User` + + :return: Instance of the class + :rtype: :class:`DirectMessagesTopic` + """ + def __init__(self, topic_id: int, user: Optional[User] = None, **kwargs): + self.topic_id: int = topic_id + self.user: Optional[User] = user # for future compatibility, currently always present + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'user' in obj: + obj['user'] = User.de_json(obj['user']) + return cls(**obj) + From 1f6c6d96d17ef9d1c83053ad7cfe8b59ac2fc0b4 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 21:57:06 +0500 Subject: [PATCH 463/480] Added the parameter direct_messages_topic_id to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendPaidMedia, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendDice, sendInvoice, sendMediaGroup, copyMessage, copyMessages, forwardMessage and forwardMessages. This parameter can be used to send a message to a direct messages chat topic. --- telebot/__init__.py | 203 ++++++++++++++++++++++++++++-------- telebot/apihelper.py | 79 ++++++++++---- telebot/async_telebot.py | 209 ++++++++++++++++++++++++++++++-------- telebot/asyncio_helper.py | 77 ++++++++++---- 4 files changed, 447 insertions(+), 121 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 59a8d7db8..8506303ce 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1691,7 +1691,8 @@ def send_message( link_preview_options : Optional[types.LinkPreviewOptions]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send text messages. @@ -1754,6 +1755,10 @@ def send_message( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1802,7 +1807,9 @@ def send_message( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, entities=entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, link_preview_options=link_preview_options, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + ) + ) def forward_message( @@ -1811,7 +1818,8 @@ def forward_message( protect_content: Optional[bool]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - video_start_timestamp: Optional[int]=None) -> types.Message: + video_start_timestamp: Optional[int]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -1841,6 +1849,10 @@ def forward_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1851,7 +1863,9 @@ def forward_message( apihelper.forward_message( self.token, chat_id, from_chat_id, message_id, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, - video_start_timestamp=video_start_timestamp)) + video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id + ) + ) def copy_message( @@ -1871,7 +1885,8 @@ def copy_message( reply_parameters: Optional[types.ReplyParameters]=None, show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, - video_start_timestamp: Optional[int]=None) -> types.MessageID: + video_start_timestamp: Optional[int]=None, + direct_messages_topic_id: Optional[int]=None) -> types.MessageID: """ Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. @@ -1933,6 +1948,10 @@ def copy_message( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -1966,8 +1985,8 @@ def copy_message( reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - video_start_timestamp=video_start_timestamp)) - + video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id + )) def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -2019,7 +2038,7 @@ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, - protect_content: Optional[bool]=None) -> List[types.MessageID]: + protect_content: Optional[bool]=None, direct_messages_topic_id: Optional[int]=None) -> List[types.MessageID]: """ Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, they are skipped. Service messages and messages with protected content can't be forwarded. Album grouping is kept for forwarded messages. @@ -2045,6 +2064,10 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in :param protect_content: Protects the contents of the forwarded message from forwarding and saving :type protect_content: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.MessageID` """ @@ -2055,13 +2078,14 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in result = apihelper.forward_messages( self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, message_thread_id=message_thread_id, - protect_content=protect_content) + protect_content=protect_content, direct_messages_topic_id=direct_messages_topic_id) return [types.MessageID.de_json(message_id) for message_id in result] def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, - protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: + protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None, + direct_messages_topic_id: Optional[int] = None) -> List[types.MessageID]: """ Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, @@ -2093,6 +2117,10 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], :param remove_caption: Pass True to copy the messages without their captions :type remove_caption: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, an array of MessageId of the sent messages is returned. :rtype: :obj:`list` of :class:`telebot.types.MessageID` """ @@ -2101,7 +2129,8 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], result = apihelper.copy_messages( self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, - message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) + message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption, + direct_messages_topic_id=direct_messages_topic_id) return [types.MessageID.de_json(message_id) for message_id in result] def send_checklist( @@ -2201,7 +2230,8 @@ def send_dice( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -2250,6 +2280,10 @@ def send_dice( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2279,7 +2313,9 @@ def send_dice( self.token, chat_id, emoji=emoji, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + ) + ) @@ -2299,7 +2335,8 @@ def send_photo( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2363,6 +2400,10 @@ def send_photo( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2396,8 +2437,10 @@ def send_photo( caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) - + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) + ) def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -2417,7 +2460,8 @@ def send_audio( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -2497,6 +2541,10 @@ def send_audio( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2532,8 +2580,10 @@ def send_audio( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) - + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) + ) def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], @@ -2550,7 +2600,8 @@ def send_voice( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -2611,6 +2662,10 @@ def send_voice( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -2641,7 +2696,7 @@ def send_voice( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) ) @@ -2664,7 +2719,8 @@ def send_document( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send general files. @@ -2737,6 +2793,10 @@ def send_document( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2781,7 +2841,8 @@ def send_document( timeout=timeout, caption=caption, thumbnail=thumbnail, caption_entities=caption_entities, disable_content_type_detection=disable_content_type_detection, visible_file_name=visible_file_name, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) ) @@ -2800,7 +2861,8 @@ def send_sticker( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -2856,6 +2918,10 @@ def send_sticker( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2890,7 +2956,8 @@ def send_sticker( reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) ) @@ -2920,7 +2987,8 @@ def send_video( show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, cover: Optional[Union[Any, str]]=None, - start_timestamp: Optional[int]=None) -> types.Message: + start_timestamp: Optional[int]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -3014,6 +3082,10 @@ def send_video( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3056,7 +3128,7 @@ def send_video( protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - cover=cover, start_timestamp=start_timestamp) + cover=cover, start_timestamp=start_timestamp, direct_messages_topic_id=direct_messages_topic_id) ) @@ -3082,7 +3154,8 @@ def send_animation( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -3165,6 +3238,10 @@ def send_animation( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3201,7 +3278,8 @@ def send_animation( thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) ) @@ -3221,7 +3299,8 @@ def send_video_note( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -3286,6 +3365,10 @@ def send_video_note( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3319,7 +3402,8 @@ def send_video_note( self.token, chat_id, data, duration=duration, length=length, reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) ) def send_paid_media( @@ -3328,7 +3412,8 @@ def send_paid_media( show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, - payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None + payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None ) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -3378,6 +3463,10 @@ def send_paid_media( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3387,7 +3476,7 @@ def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - payload=payload, allow_paid_broadcast=allow_paid_broadcast) + payload=payload, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) ) @@ -3405,7 +3494,8 @@ def send_media_group( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> List[types.Message]: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -3449,6 +3539,10 @@ def send_media_group( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -3482,7 +3576,8 @@ def send_media_group( result = apihelper.send_media_group( self.token, chat_id, media, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) return [types.Message.de_json(msg) for msg in result] @@ -3503,7 +3598,8 @@ def send_location( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -3566,6 +3662,10 @@ def send_location( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3596,7 +3696,7 @@ def send_location( disable_notification=disable_notification, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, proximity_alert_radius=proximity_alert_radius, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) ) @@ -3728,7 +3828,8 @@ def send_venue( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -3798,6 +3899,10 @@ def send_venue( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3828,7 +3933,7 @@ def send_venue( foursquare_type=foursquare_type, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, google_place_id=google_place_id, google_place_type=google_place_type, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) ) @@ -3845,7 +3950,8 @@ def send_contact( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -3902,6 +4008,10 @@ def send_contact( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3931,7 +4041,8 @@ def send_contact( self.token, chat_id, phone_number, first_name, last_name=last_name, vcard=vcard, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, - business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) ) @@ -5374,7 +5485,8 @@ def send_invoice( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Sends invoice. @@ -5487,6 +5599,10 @@ def send_invoice( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5526,7 +5642,8 @@ def send_invoice( provider_data=provider_data, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) ) def create_invoice_link(self, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index cba38bbdd..be8844373 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -247,7 +247,8 @@ def send_message( parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, link_preview_options=None, - business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): + business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, + direct_messages_topic_id=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -274,6 +275,8 @@ def send_message( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, method='post') @@ -427,7 +430,7 @@ def get_chat_member(token, chat_id, user_id): def forward_message( token, chat_id, from_chat_id, message_id, disable_notification=None, timeout=None, protect_content=None, message_thread_id=None, - video_start_timestamp=None): + video_start_timestamp=None, direct_messages_topic_id=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -440,13 +443,15 @@ def forward_message( payload['message_thread_id'] = message_thread_id if video_start_timestamp: payload['video_start_timestamp'] = video_start_timestamp + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None, - video_start_timestamp=None): + video_start_timestamp=None, direct_messages_topic_id=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -473,6 +478,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['allow_paid_broadcast'] = allow_paid_broadcast if video_start_timestamp: payload['video_start_timestamp'] = video_start_timestamp + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) def send_checklist( @@ -510,7 +517,7 @@ def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, - business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): + business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -533,6 +540,8 @@ def send_dice( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) @@ -542,7 +551,8 @@ def send_photo( parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, + direct_messages_topic_id=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -580,13 +590,15 @@ def send_photo( payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, payload=None, allow_paid_broadcast=None): + business_connection_id=None, payload=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -612,6 +624,8 @@ def send_paid_media( _payload['payload'] = payload if allow_paid_broadcast is not None: _payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + _payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request( token, method_url, params=_payload, method='post' if files else 'get', @@ -622,7 +636,7 @@ def send_media_group( token, chat_id, media, disable_notification=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendMediaGroup' media_json, files = convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -642,6 +656,8 @@ def send_media_group( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request( token, method_url, params=payload, method='post' if files else 'get', @@ -655,7 +671,7 @@ def send_location( timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -684,6 +700,8 @@ def send_location( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) @@ -740,7 +758,7 @@ def send_venue( foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -769,6 +787,8 @@ def send_venue( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) @@ -776,7 +796,7 @@ def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -801,6 +821,8 @@ def send_contact( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) @@ -822,7 +844,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, - cover=None, start_timestamp=None): + cover=None, start_timestamp=None, direct_messages_topic_id=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -884,6 +906,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['cover'] = cover if start_timestamp: payload['start_timestamp'] = start_timestamp + if direct_messages_topic_id: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') @@ -893,7 +917,7 @@ def send_animation( parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, has_spoiler=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -943,13 +967,15 @@ def send_animation( payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -983,13 +1009,15 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, message_thread_id=None, reply_parameters=None,business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -1029,13 +1057,15 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -1081,6 +1111,8 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1088,7 +1120,7 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -1135,6 +1167,8 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1726,7 +1760,7 @@ def send_invoice( disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1814,6 +1848,8 @@ def send_invoice( payload['provider_token'] = provider_token if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) @@ -2464,7 +2500,7 @@ def delete_messages(token, chat_id, message_ids): return _make_request(token, method_url, params=payload) def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, - message_thread_id=None, protect_content=None): + message_thread_id=None, protect_content=None, direct_messages_topic_id=None): method_url = 'forwardMessages' payload = { 'chat_id': chat_id, @@ -2477,10 +2513,13 @@ def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notifica payload['message_thread_id'] = message_thread_id if protect_content is not None: payload['protect_content'] = protect_content + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, - message_thread_id=None, protect_content=None, remove_caption=None, show_caption_above_media=None): + message_thread_id=None, protect_content=None, remove_caption=None, show_caption_above_media=None, + direct_messages_topic_id=None): method_url = 'copyMessages' payload = { 'chat_id': chat_id, @@ -2497,6 +2536,8 @@ def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notificatio payload['remove_caption'] = remove_caption if show_caption_above_media is not None: payload['show_caption_above_media'] = show_caption_above_media + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return _make_request(token, method_url, params=payload) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index fe8013135..0be94c0a8 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3213,7 +3213,8 @@ async def send_message( link_preview_options: Optional[types.LinkPreviewOptions]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send text messages. @@ -3276,6 +3277,10 @@ async def send_message( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3331,7 +3336,10 @@ async def send_message( self.token, chat_id, text, reply_markup, parse_mode, disable_notification, timeout, entities, protect_content, message_thread_id, reply_parameters, link_preview_options, business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) + ) async def forward_message( self, chat_id: Union[int, str], from_chat_id: Union[int, str], @@ -3339,7 +3347,8 @@ async def forward_message( protect_content: Optional[bool]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, - video_start_timestamp: Optional[int]=None) -> types.Message: + video_start_timestamp: Optional[int]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -3369,6 +3378,10 @@ async def forward_message( :param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only :type message_thread_id: :obj:`int` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3378,7 +3391,9 @@ async def forward_message( return types.Message.de_json( await asyncio_helper.forward_message(self.token, chat_id=chat_id, from_chat_id=from_chat_id, message_id=message_id, disable_notification=disable_notification, protect_content=protect_content, - timeout=timeout, message_thread_id=message_thread_id, video_start_timestamp=video_start_timestamp)) + timeout=timeout, message_thread_id=message_thread_id, video_start_timestamp=video_start_timestamp, + direct_messages_topic_id=direct_messages_topic_id) + ) async def copy_message( self, chat_id: Union[int, str], @@ -3397,7 +3412,8 @@ async def copy_message( reply_parameters: Optional[types.ReplyParameters]=None, show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, - video_start_timestamp: Optional[bool]=None) -> types.MessageID: + video_start_timestamp: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.MessageID: """ Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, @@ -3460,6 +3476,10 @@ async def copy_message( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -3494,7 +3514,8 @@ async def copy_message( disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, timeout=timeout, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, - allow_paid_broadcast=allow_paid_broadcast, video_start_timestamp=video_start_timestamp)) + allow_paid_broadcast=allow_paid_broadcast, video_start_timestamp=video_start_timestamp, + direct_messages_topic_id=direct_messages_topic_id)) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -3544,7 +3565,8 @@ async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int] return await asyncio_helper.delete_messages(self.token, chat_id, message_ids) async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, - message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: + message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> List[types.MessageID]: """ Use this method to forward multiple messages of any kind. If some of the specified messages can't be found or forwarded, they are skipped. Service messages and messages with protected content can't be forwarded. @@ -3570,18 +3592,24 @@ async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[s :param protect_content: Protects the contents of the forwarded message from forwarding and saving :type protect_content: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.MessageID` """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, protect_content) + result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, protect_content, + direct_messages_topic_id=direct_messages_topic_id) return [types.MessageID.de_json(message_id) for message_id in result] async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, - protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: + protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None, + direct_messages_topic_id: Optional[int] = None) -> List[types.MessageID]: """ Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. @@ -3611,13 +3639,17 @@ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, :param remove_caption: Pass True to copy the messages without their captions :type remove_caption: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, an array of MessageId of the sent messages is returned. :rtype: :obj:`list` of :class:`telebot.types.MessageID` """ disable_notification = self.disable_notification if disable_notification is None else disable_notification protect_content = self.protect_content if protect_content is None else protect_content result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, - protect_content, remove_caption) + protect_content, remove_caption, direct_messages_topic_id) return [types.MessageID.de_json(message_id) for message_id in result] async def send_checklist( @@ -3717,7 +3749,8 @@ async def send_dice( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -3766,6 +3799,10 @@ async def send_dice( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3797,8 +3834,9 @@ async def send_dice( await asyncio_helper.send_dice( self.token, chat_id, emoji, disable_notification, reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast)) - + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_photo( self, chat_id: Union[int, str], photo: Union[Any, str], @@ -3816,7 +3854,8 @@ async def send_photo( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -3880,6 +3919,10 @@ async def send_photo( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -3914,7 +3957,10 @@ async def send_photo( self.token, chat_id, photo, caption, reply_markup, parse_mode, disable_notification, timeout, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_audio( self, chat_id: Union[int, str], audio: Union[Any, str], @@ -3934,7 +3980,8 @@ async def send_audio( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -4014,6 +4061,10 @@ async def send_audio( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4050,7 +4101,10 @@ async def send_audio( await asyncio_helper.send_audio( self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, - caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_voice( self, chat_id: Union[int, str], voice: Union[Any, str], @@ -4067,7 +4121,8 @@ async def send_voice( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -4128,6 +4183,10 @@ async def send_voice( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -4160,7 +4219,9 @@ async def send_voice( self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast)) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_document( self, chat_id: Union[int, str], document: Union[Any, str], @@ -4182,7 +4243,8 @@ async def send_document( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send general files. @@ -4255,6 +4317,10 @@ async def send_document( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4303,7 +4369,10 @@ async def send_document( disable_notification = disable_notification, timeout = timeout, caption = caption, thumbnail= thumbnail, caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content, - message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_sticker( self, chat_id: Union[int, str], sticker: Union[Any, str], @@ -4319,7 +4388,8 @@ async def send_sticker( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -4375,6 +4445,10 @@ async def send_sticker( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4441,7 +4515,8 @@ async def send_video( show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, cover: Optional[Union[Any, str]]=None, - start_timestamp: Optional[int]=None) -> types.Message: + start_timestamp: Optional[int]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4533,6 +4608,9 @@ async def send_video( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of a topic in a forum supergroup or channel, in which the message will be sent + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4575,7 +4653,8 @@ async def send_video( self.token, chat_id, video, duration, caption, reply_markup, parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, cover=cover, start_timestamp=start_timestamp)) + show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, cover=cover, start_timestamp=start_timestamp, + direct_messages_topic_id=direct_messages_topic_id)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -4599,7 +4678,8 @@ async def send_animation( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -4682,6 +4762,10 @@ async def send_animation( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4719,7 +4803,8 @@ async def send_animation( self.token, chat_id, animation, duration, caption, reply_markup, parse_mode, disable_notification, timeout, thumbnail, caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, - message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) + message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -4737,7 +4822,8 @@ async def send_video_note( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -4802,6 +4888,10 @@ async def send_video_note( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4837,7 +4927,7 @@ async def send_video_note( await asyncio_helper.send_video_note( self.token, chat_id, data, duration, length, reply_markup, disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast)) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id)) async def send_paid_media( self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], @@ -4845,7 +4935,8 @@ async def send_paid_media( show_caption_above_media: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, - payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None) -> types.Message: + payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -4894,6 +4985,10 @@ async def send_paid_media( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4903,7 +4998,9 @@ async def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - payload=payload, allow_paid_broadcast=allow_paid_broadcast)) + payload=payload, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_media_group( self, chat_id: Union[int, str], @@ -4919,7 +5016,8 @@ async def send_media_group( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> List[types.Message]: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -4963,6 +5061,10 @@ async def send_media_group( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -4997,7 +5099,7 @@ async def send_media_group( result = await asyncio_helper.send_media_group( self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) return [types.Message.de_json(msg) for msg in result] async def send_location( @@ -5017,7 +5119,8 @@ async def send_location( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -5080,6 +5183,10 @@ async def send_location( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -5112,7 +5219,9 @@ async def send_location( self.token, chat_id, latitude, longitude, live_period, reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, - protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) + ) async def edit_message_live_location( self, latitude: float, longitude: float, @@ -5238,7 +5347,8 @@ async def send_venue( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -5308,6 +5418,10 @@ async def send_venue( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -5341,7 +5455,8 @@ async def send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, disable_notification, reply_markup, timeout, google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast)) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + ) async def send_contact( @@ -5358,7 +5473,8 @@ async def send_contact( reply_parameters: Optional[types.ReplyParameters]=None, business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -5416,6 +5532,10 @@ async def send_contact( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -5447,7 +5567,9 @@ async def send_contact( await asyncio_helper.send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, disable_notification, reply_markup, timeout, - protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id) + ) async def send_chat_action( @@ -6827,7 +6949,8 @@ async def send_invoice( message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, message_effect_id: Optional[str]=None, - allow_paid_broadcast: Optional[bool]=None) -> types.Message: + allow_paid_broadcast: Optional[bool]=None, + direct_messages_topic_id: Optional[int]=None) -> types.Message: """ Sends invoice. @@ -6940,6 +7063,10 @@ async def send_invoice( of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` + :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; + required if the message is sent to a direct messages chat + :type direct_messages_topic_id: :obj:`int` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -6974,7 +7101,9 @@ async def send_invoice( send_phone_number_to_provider, send_email_to_provider, is_flexible, disable_notification, reply_markup, provider_data, timeout, max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + direct_messages_topic_id=direct_messages_topic_id + ) return types.Message.de_json(result) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index bc50068f6..704029994 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -284,7 +284,7 @@ async def send_message( parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -311,6 +311,8 @@ async def send_message( params['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: params['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + params['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_name, params=params, method='post') @@ -429,7 +431,7 @@ async def get_chat_member(token, chat_id, user_id): async def forward_message( token, chat_id, from_chat_id, message_id, disable_notification=None, timeout=None, protect_content=None, - message_thread_id=None, video_start_timestamp=None): + message_thread_id=None, video_start_timestamp=None, direct_messages_topic_id=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -442,13 +444,15 @@ async def forward_message( payload['message_thread_id'] = message_thread_id if video_start_timestamp: payload['video_start_timestamp'] = video_start_timestamp + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload) async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, - allow_paid_broadcast=None, video_start_timestamp=None): + allow_paid_broadcast=None, video_start_timestamp=None, direct_messages_topic_id=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -475,6 +479,8 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['allow_paid_broadcast'] = allow_paid_broadcast if video_start_timestamp: payload['video_start_timestamp'] = video_start_timestamp + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload) async def send_checklist( @@ -511,7 +517,8 @@ async def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, - message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, + direct_messages_topic_id=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -543,7 +550,8 @@ async def send_photo( parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, - business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None): + business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, + direct_messages_topic_id=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -581,13 +589,15 @@ async def send_photo( payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, payload=None, allow_paid_broadcast=None): + business_connection_id=None, payload=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -614,6 +624,8 @@ async def send_paid_media( _payload['payload'] = payload if allow_paid_broadcast is not None: _payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + _payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request( token, method_url, params=_payload, @@ -624,7 +636,7 @@ async def send_media_group( token, chat_id, media, disable_notification=None, timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendMediaGroup' media_json, files = await convert_input_media_array(media) payload = {'chat_id': chat_id, 'media': media_json} @@ -644,6 +656,8 @@ async def send_media_group( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request( token, method_url, params=payload, method='post' if files else 'get', @@ -656,7 +670,7 @@ async def send_location( reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -685,6 +699,8 @@ async def send_location( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload) @@ -742,7 +758,7 @@ async def send_venue( reply_markup=None, timeout=None, google_place_id=None, google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -771,6 +787,8 @@ async def send_venue( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload) @@ -778,7 +796,7 @@ async def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -822,7 +840,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None, thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, cover=None, start_timestamp=None): + message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, cover=None, start_timestamp=None, + direct_messages_topic_id=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -884,6 +903,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['cover'] = cover if start_timestamp: payload['start_timestamp'] = start_timestamp + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -892,7 +913,7 @@ async def send_animation( parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, width=None, height=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -942,13 +963,15 @@ async def send_animation( payload['show_caption_above_media'] = show_caption_above_media if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -982,12 +1005,15 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_ payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, - message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None): + message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, + direct_messages_topic_id=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -1027,13 +1053,15 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, rep payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -1079,6 +1107,8 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1086,7 +1116,7 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None, message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None): + allow_paid_broadcast=None, direct_messages_topic_id=None): method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -1133,6 +1163,8 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1719,7 +1751,8 @@ async def send_invoice( send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None, disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, - protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, allow_paid_broadcast=None): + protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, allow_paid_broadcast=None, + direct_messages_topic_id=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1808,6 +1841,8 @@ async def send_invoice( payload['provider_token'] = provider_token if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id return await _process_request(token, method_url, params=payload) @@ -2428,7 +2463,7 @@ async def delete_messages(token, chat_id, message_ids): return await _process_request(token, method_url, params=payload) async def forward_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, - message_thread_id=None, protect_content=None): + message_thread_id=None, protect_content=None, direct_messages_topic_id=None): method_url = 'forwardMessages' payload = { 'chat_id': chat_id, @@ -2441,12 +2476,14 @@ async def forward_messages(token, chat_id, from_chat_id, message_ids, disable_no payload['message_thread_id'] = message_thread_id if protect_content is not None: payload['protect_content'] = protect_content + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id result = await _process_request(token, method_url, params=payload) return result async def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notification=None, - message_thread_id=None, protect_content=None, remove_caption=None): + message_thread_id=None, protect_content=None, remove_caption=None, direct_messages_topic_id=None): method_url = 'copyMessages' payload = { 'chat_id': chat_id, @@ -2461,6 +2498,8 @@ async def copy_messages(token, chat_id, from_chat_id, message_ids, disable_notif payload['protect_content'] = protect_content if remove_caption is not None: payload['remove_caption'] = remove_caption + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id result = await _process_request(token, method_url, params=payload) return result From 9a44dba54af0d8ae1214465d141fb5d8ed9b8858 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 22:34:02 +0500 Subject: [PATCH 464/480] Added the class SuggestedPostParameters and the parameter suggested_post_parameters to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendPaidMedia, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendDice, sendInvoice, copyMessage, forwardMessage. This parameter can be used to send a suggested post to a direct messages chat topic. --- telebot/__init__.py | 180 ++++++++++++++++++++++++++++------- telebot/apihelper.py | 67 +++++++++---- telebot/async_telebot.py | 191 +++++++++++++++++++++++++++++++------- telebot/asyncio_helper.py | 70 ++++++++++---- telebot/types.py | 61 ++++++++++++ 5 files changed, 467 insertions(+), 102 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 8506303ce..ecad66fa8 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -1692,7 +1692,8 @@ def send_message( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send text messages. @@ -1759,6 +1760,11 @@ def send_message( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1807,7 +1813,8 @@ def send_message( reply_markup=reply_markup, parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, entities=entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, link_preview_options=link_preview_options, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters ) ) @@ -1819,7 +1826,8 @@ def forward_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, video_start_timestamp: Optional[int]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -1853,6 +1861,11 @@ def forward_message( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -1863,7 +1876,8 @@ def forward_message( apihelper.forward_message( self.token, chat_id, from_chat_id, message_id, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, - video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id + video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters ) ) @@ -1886,7 +1900,8 @@ def copy_message( show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, video_start_timestamp: Optional[int]=None, - direct_messages_topic_id: Optional[int]=None) -> types.MessageID: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.MessageID: """ Use this method to copy messages of any kind. Service messages, paid media messages, giveaway messages, giveaway winners messages, and invoice messages can't be copied. @@ -1952,6 +1967,11 @@ def copy_message( :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -1985,7 +2005,8 @@ def copy_message( reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id + video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters )) def delete_message(self, chat_id: Union[int, str], message_id: int, @@ -2231,7 +2252,8 @@ def send_dice( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -2284,6 +2306,11 @@ def send_dice( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2313,7 +2340,8 @@ def send_dice( self.token, chat_id, emoji=emoji, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters ) ) @@ -2336,7 +2364,8 @@ def send_photo( message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -2404,6 +2433,11 @@ def send_photo( :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` @@ -2438,7 +2472,7 @@ def send_photo( message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -2461,7 +2495,8 @@ def send_audio( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -2545,6 +2580,11 @@ def send_audio( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2581,7 +2621,7 @@ def send_audio( timeout=timeout, thumbnail=thumbnail, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -2601,7 +2641,8 @@ def send_voice( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -2666,6 +2707,11 @@ def send_voice( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -2696,7 +2742,9 @@ def send_voice( parse_mode=parse_mode, disable_notification=disable_notification, timeout=timeout, caption_entities=caption_entities, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters + ) ) @@ -2720,7 +2768,8 @@ def send_document( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send general files. @@ -2797,6 +2846,11 @@ def send_document( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2842,7 +2896,7 @@ def send_document( disable_content_type_detection=disable_content_type_detection, visible_file_name=visible_file_name, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) @@ -2862,7 +2916,8 @@ def send_sticker( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -2922,6 +2977,11 @@ def send_sticker( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2957,7 +3017,7 @@ def send_sticker( protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) @@ -2988,7 +3048,8 @@ def send_video( allow_paid_broadcast: Optional[bool]=None, cover: Optional[Union[Any, str]]=None, start_timestamp: Optional[int]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -3086,6 +3147,11 @@ def send_video( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3128,7 +3194,8 @@ def send_video( protect_content=protect_content, message_thread_id=message_thread_id, has_spoiler=has_spoiler, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - cover=cover, start_timestamp=start_timestamp, direct_messages_topic_id=direct_messages_topic_id) + cover=cover, start_timestamp=start_timestamp, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters) ) @@ -3155,7 +3222,8 @@ def send_animation( message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -3242,6 +3310,11 @@ def send_animation( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3279,7 +3352,7 @@ def send_animation( width=width, height=height, message_thread_id=message_thread_id, reply_parameters=reply_parameters, has_spoiler=has_spoiler, business_connection_id=business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) @@ -3300,7 +3373,8 @@ def send_video_note( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -3369,6 +3443,11 @@ def send_video_note( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3403,7 +3482,7 @@ def send_video_note( disable_notification=disable_notification, timeout=timeout, thumbnail=thumbnail, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) def send_paid_media( @@ -3413,7 +3492,8 @@ def send_paid_media( protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None ) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -3467,6 +3547,11 @@ def send_paid_media( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3476,7 +3561,8 @@ def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - payload=payload, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + payload=payload, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters) ) @@ -3599,7 +3685,8 @@ def send_location( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -3666,6 +3753,11 @@ def send_location( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3696,7 +3788,8 @@ def send_location( disable_notification=disable_notification, timeout=timeout, horizontal_accuracy=horizontal_accuracy, heading=heading, proximity_alert_radius=proximity_alert_radius, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters) ) @@ -3829,7 +3922,8 @@ def send_venue( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -3903,6 +3997,11 @@ def send_venue( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3933,7 +4032,8 @@ def send_venue( foursquare_type=foursquare_type, disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, google_place_id=google_place_id, google_place_type=google_place_type, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, - message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters) ) @@ -3951,7 +4051,8 @@ def send_contact( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -4012,6 +4113,11 @@ def send_contact( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4042,7 +4148,7 @@ def send_contact( disable_notification=disable_notification, reply_markup=reply_markup, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) @@ -5486,7 +5592,8 @@ def send_invoice( reply_parameters: Optional[types.ReplyParameters]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Sends invoice. @@ -5603,6 +5710,11 @@ def send_invoice( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -5643,7 +5755,7 @@ def send_invoice( message_thread_id=message_thread_id, reply_parameters=reply_parameters, max_tip_amount=max_tip_amount, suggested_tip_amounts=suggested_tip_amounts, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) def create_invoice_link(self, diff --git a/telebot/apihelper.py b/telebot/apihelper.py index be8844373..beb778d06 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -248,7 +248,7 @@ def send_message( entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendMessage' payload = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -277,6 +277,8 @@ def send_message( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, method='post') @@ -430,7 +432,7 @@ def get_chat_member(token, chat_id, user_id): def forward_message( token, chat_id, from_chat_id, message_id, disable_notification=None, timeout=None, protect_content=None, message_thread_id=None, - video_start_timestamp=None, direct_messages_topic_id=None): + video_start_timestamp=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -445,13 +447,15 @@ def forward_message( payload['video_start_timestamp'] = video_start_timestamp if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, allow_paid_broadcast=None, - video_start_timestamp=None, direct_messages_topic_id=None): + video_start_timestamp=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -480,6 +484,8 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m payload['video_start_timestamp'] = video_start_timestamp if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) def send_checklist( @@ -517,7 +523,8 @@ def send_dice( token, chat_id, emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, - business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, + suggested_post_parameters=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -542,6 +549,8 @@ def send_dice( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -552,7 +561,7 @@ def send_photo( caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -592,13 +601,16 @@ def send_photo( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, payload=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + business_connection_id=None, payload=None, allow_paid_broadcast=None, direct_messages_topic_id=None, + suggested_post_parameters=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -626,6 +638,8 @@ def send_paid_media( _payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: _payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + _payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request( token, method_url, params=_payload, method='post' if files else 'get', @@ -671,7 +685,8 @@ def send_location( timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, + suggested_post_parameters=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -702,6 +717,8 @@ def send_location( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -758,7 +775,7 @@ def send_venue( foursquare_id=None, foursquare_type=None, disable_notification=None, reply_markup=None, timeout=None, google_place_id=None, google_place_type=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -789,6 +806,8 @@ def send_venue( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -796,7 +815,7 @@ def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -823,6 +842,8 @@ def send_contact( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) @@ -844,7 +865,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None, reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, - cover=None, start_timestamp=None, direct_messages_topic_id=None): + cover=None, start_timestamp=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -908,6 +929,8 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_markup=N payload['start_timestamp'] = start_timestamp if direct_messages_topic_id: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -917,7 +940,7 @@ def send_animation( parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, width=None, height=None, message_thread_id=None, reply_parameters=None, has_spoiler=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -969,13 +992,15 @@ def send_animation( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -1011,13 +1036,15 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup= payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, message_thread_id=None, reply_parameters=None,business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -1059,13 +1086,15 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_mark payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -1113,6 +1142,8 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1120,7 +1151,7 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content = None, message_thread_id=None, emoji=None, reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -1169,6 +1200,8 @@ def send_data(token, chat_id, data, data_type, reply_markup=None, parse_mode=Non payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload, files=files, method='post') @@ -1760,7 +1793,7 @@ def send_invoice( disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1850,6 +1883,8 @@ def send_invoice( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return _make_request(token, method_url, params=payload) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 0be94c0a8..04325e1c0 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3214,7 +3214,8 @@ async def send_message( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send text messages. @@ -3281,6 +3282,11 @@ async def send_message( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3337,7 +3343,7 @@ async def send_message( reply_markup, parse_mode, disable_notification, timeout, entities, protect_content, message_thread_id, reply_parameters, link_preview_options, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -3348,7 +3354,8 @@ async def forward_message( timeout: Optional[int]=None, message_thread_id: Optional[int]=None, video_start_timestamp: Optional[int]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to forward messages of any kind. @@ -3382,6 +3389,11 @@ async def forward_message( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3392,7 +3404,7 @@ async def forward_message( await asyncio_helper.forward_message(self.token, chat_id=chat_id, from_chat_id=from_chat_id, message_id=message_id, disable_notification=disable_notification, protect_content=protect_content, timeout=timeout, message_thread_id=message_thread_id, video_start_timestamp=video_start_timestamp, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) async def copy_message( @@ -3413,7 +3425,8 @@ async def copy_message( show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, video_start_timestamp: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.MessageID: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.MessageID: """ Use this method to copy messages of any kind. If some of the specified messages can't be found or copied, they are skipped. Service messages, paid media messages, giveaway messages, giveaway winners messages, @@ -3480,6 +3493,11 @@ async def copy_message( :param direct_messages_topic_id: Identifier of the direct messages topic to which the message will be sent; required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` @@ -3515,7 +3533,9 @@ async def copy_message( reply_parameters=reply_parameters, reply_markup=reply_markup, timeout=timeout, message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, video_start_timestamp=video_start_timestamp, - direct_messages_topic_id=direct_messages_topic_id)) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters + ) + ) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: @@ -3750,7 +3770,8 @@ async def send_dice( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned. @@ -3803,6 +3824,11 @@ async def send_dice( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3834,7 +3860,7 @@ async def send_dice( await asyncio_helper.send_dice( self.token, chat_id, emoji, disable_notification, reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -3855,7 +3881,8 @@ async def send_photo( message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send photos. On success, the sent Message is returned. @@ -3924,6 +3951,11 @@ async def send_photo( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -3958,7 +3990,7 @@ async def send_photo( parse_mode, disable_notification, timeout, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -3981,7 +4013,8 @@ async def send_audio( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio must be in the .MP3 or .M4A format. On success, the sent Message is returned. Bots can currently send audio files of up to 50 MB in size, @@ -4065,6 +4098,11 @@ async def send_audio( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4102,7 +4140,7 @@ async def send_audio( self.token, chat_id, audio, caption, duration, performer, title, reply_markup, parse_mode, disable_notification, timeout, thumbnail, caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -4122,7 +4160,8 @@ async def send_voice( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. @@ -4187,6 +4226,11 @@ async def send_voice( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode @@ -4219,7 +4263,7 @@ async def send_voice( self.token, chat_id, voice, caption, duration, reply_markup, parse_mode, disable_notification, timeout, caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -4244,7 +4288,8 @@ async def send_document( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send general files. @@ -4321,6 +4366,11 @@ async def send_document( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4370,7 +4420,7 @@ async def send_document( caption_entities = caption_entities, disable_content_type_detection = disable_content_type_detection, visible_file_name = visible_file_name, protect_content = protect_content, message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) @@ -4389,7 +4439,8 @@ async def send_sticker( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send static .WEBP, animated .TGS, or video .WEBM stickers. On success, the sent Message is returned. @@ -4449,6 +4500,11 @@ async def send_sticker( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4487,7 +4543,10 @@ async def send_sticker( reply_markup=reply_markup, disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, - message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) + message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, + suggested_post_parameters=suggested_post_parameters, direct_messages_topic_id=direct_messages_topic_id + ) + ) async def send_video( self, chat_id: Union[int, str], video: Union[Any, str], @@ -4516,7 +4575,8 @@ async def send_video( allow_paid_broadcast: Optional[bool]=None, cover: Optional[Union[Any, str]]=None, start_timestamp: Optional[int]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). @@ -4611,6 +4671,11 @@ async def send_video( :param direct_messages_topic_id: Identifier of a topic in a forum supergroup or channel, in which the message will be sent :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4654,7 +4719,7 @@ async def send_video( parse_mode, supports_streaming, disable_notification, timeout, thumbnail, width, height, caption_entities, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, cover=cover, start_timestamp=start_timestamp, - direct_messages_topic_id=direct_messages_topic_id)) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters)) async def send_animation( self, chat_id: Union[int, str], animation: Union[Any, str], @@ -4679,7 +4744,8 @@ async def send_animation( message_effect_id: Optional[str]=None, show_caption_above_media: Optional[bool]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. @@ -4766,6 +4832,11 @@ async def send_animation( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4804,7 +4875,7 @@ async def send_animation( reply_markup, parse_mode, disable_notification, timeout, thumbnail, caption_entities, width, height, protect_content, message_thread_id, has_spoiler, reply_parameters, business_connection_id, message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id)) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters)) async def send_video_note( self, chat_id: Union[int, str], data: Union[Any, str], @@ -4823,7 +4894,8 @@ async def send_video_note( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ As of v.4.0, Telegram clients support rounded square MPEG4 videos of up to 1 minute long. Use this method to send video messages. On success, the sent Message is returned. @@ -4892,6 +4964,11 @@ async def send_video_note( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4927,7 +5004,10 @@ async def send_video_note( await asyncio_helper.send_video_note( self.token, chat_id, data, duration, length, reply_markup, disable_notification, timeout, thumbnail, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id)) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters + ) + ) async def send_paid_media( self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], @@ -4936,7 +5016,8 @@ async def send_paid_media( protect_content: Optional[bool]=None, reply_parameters: Optional[types.ReplyParameters]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, business_connection_id: Optional[str]=None, payload: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send paid media to channel chats. On success, the sent Message is returned. @@ -4989,6 +5070,11 @@ async def send_paid_media( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -4998,7 +5084,8 @@ async def send_paid_media( caption_entities=caption_entities, show_caption_above_media=show_caption_above_media, disable_notification=disable_notification, protect_content=protect_content, reply_parameters=reply_parameters, reply_markup=reply_markup, business_connection_id=business_connection_id, - payload=payload, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id + payload=payload, allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters ) ) @@ -5017,7 +5104,8 @@ async def send_media_group( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> List[types.Message]: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -5065,6 +5153,11 @@ async def send_media_group( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -5099,7 +5192,8 @@ async def send_media_group( result = await asyncio_helper.send_media_group( self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, + suggested_post_parameters=suggested_post_parameters) return [types.Message.de_json(msg) for msg in result] async def send_location( @@ -5120,7 +5214,8 @@ async def send_location( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send point on the map. On success, the sent Message is returned. @@ -5187,6 +5282,11 @@ async def send_location( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -5220,7 +5320,8 @@ async def send_location( reply_markup, disable_notification, timeout, horizontal_accuracy, heading, proximity_alert_radius, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters + ) ) async def edit_message_live_location( @@ -5348,7 +5449,8 @@ async def send_venue( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. @@ -5423,6 +5525,11 @@ async def send_venue( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -5455,7 +5562,7 @@ async def send_venue( self.token, chat_id, latitude, longitude, title, address, foursquare_id, foursquare_type, disable_notification, reply_markup, timeout, google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) @@ -5474,7 +5581,8 @@ async def send_contact( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Use this method to send phone contacts. On success, the sent Message is returned. @@ -5536,6 +5644,11 @@ async def send_contact( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -5568,7 +5681,7 @@ async def send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, disable_notification, reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id) + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters) ) @@ -6950,7 +7063,8 @@ async def send_invoice( reply_parameters: Optional[types.ReplyParameters]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None) -> types.Message: + direct_messages_topic_id: Optional[int]=None, + suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> types.Message: """ Sends invoice. @@ -7067,6 +7181,11 @@ async def send_invoice( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` + :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; + for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post + is automatically declined. + :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` + :return: On success, the sent Message is returned. :rtype: :obj:`types.Message` """ @@ -7102,7 +7221,7 @@ async def send_invoice( reply_markup, provider_data, timeout, max_tip_amount, suggested_tip_amounts, protect_content, message_thread_id, reply_parameters, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast, - direct_messages_topic_id=direct_messages_topic_id + direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) return types.Message.de_json(result) diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 704029994..05ad2a8a0 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -284,7 +284,7 @@ async def send_message( parse_mode=None, disable_notification=None, timeout=None, entities=None, protect_content=None, message_thread_id=None, reply_parameters=None, link_preview_options=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_name = 'sendMessage' params = {'chat_id': str(chat_id), 'text': text} if link_preview_options is not None: @@ -313,6 +313,8 @@ async def send_message( params['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: params['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + params['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_name, params=params, method='post') @@ -431,7 +433,8 @@ async def get_chat_member(token, chat_id, user_id): async def forward_message( token, chat_id, from_chat_id, message_id, disable_notification=None, timeout=None, protect_content=None, - message_thread_id=None, video_start_timestamp=None, direct_messages_topic_id=None): + message_thread_id=None, video_start_timestamp=None, direct_messages_topic_id=None, + suggested_post_parameters=None): method_url = r'forwardMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if disable_notification is not None: @@ -446,13 +449,15 @@ async def forward_message( payload['video_start_timestamp'] = video_start_timestamp if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None, reply_parameters=None, show_caption_above_media=None, - allow_paid_broadcast=None, video_start_timestamp=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, video_start_timestamp=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'copyMessage' payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id} if caption is not None: @@ -481,6 +486,8 @@ async def copy_message(token, chat_id, from_chat_id, message_id, caption=None, p payload['video_start_timestamp'] = video_start_timestamp if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) async def send_checklist( @@ -518,7 +525,7 @@ async def send_dice( emoji=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendDice' payload = {'chat_id': chat_id} if emoji: @@ -541,6 +548,10 @@ async def send_dice( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) @@ -551,7 +562,7 @@ async def send_photo( caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendPhoto' payload = {'chat_id': chat_id} files = None @@ -591,13 +602,16 @@ async def send_photo( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_paid_media( token, chat_id, star_count, media, caption=None, parse_mode=None, caption_entities=None, show_caption_above_media=None, disable_notification=None, protect_content=None, reply_parameters=None, reply_markup=None, - business_connection_id=None, payload=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + business_connection_id=None, payload=None, allow_paid_broadcast=None, direct_messages_topic_id=None, + suggested_post_parameters=None): method_url = r'sendPaidMedia' media_json, files = convert_input_media_array(media) _payload = {'chat_id': chat_id, 'star_count': star_count, 'media': media_json} @@ -626,6 +640,8 @@ async def send_paid_media( _payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: _payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + _payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request( token, method_url, params=_payload, @@ -670,7 +686,7 @@ async def send_location( reply_markup=None, disable_notification=None, timeout=None, horizontal_accuracy=None, heading=None, proximity_alert_radius=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendLocation' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude} if live_period: @@ -701,6 +717,8 @@ async def send_location( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) @@ -758,7 +776,7 @@ async def send_venue( reply_markup=None, timeout=None, google_place_id=None, google_place_type=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVenue' payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address} if foursquare_id: @@ -789,6 +807,8 @@ async def send_venue( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) @@ -796,7 +816,7 @@ async def send_contact( token, chat_id, phone_number, first_name, last_name=None, vcard=None, disable_notification=None, reply_markup=None, timeout=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendContact' payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name} if last_name: @@ -821,6 +841,10 @@ async def send_contact( payload['message_effect_id'] = message_effect_id if allow_paid_broadcast is not None: payload['allow_paid_broadcast'] = allow_paid_broadcast + if direct_messages_topic_id is not None: + payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) @@ -841,7 +865,7 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m thumbnail=None, width=None, height=None, caption_entities=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, allow_paid_broadcast=None, cover=None, start_timestamp=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVideo' payload = {'chat_id': chat_id} files = None @@ -905,6 +929,8 @@ async def send_video(token, chat_id, data, duration=None, caption=None, reply_m payload['start_timestamp'] = start_timestamp if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -913,7 +939,7 @@ async def send_animation( parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, width=None, height=None, protect_content=None, message_thread_id=None, has_spoiler=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, show_caption_above_media=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendAnimation' payload = {'chat_id': chat_id} files = None @@ -965,13 +991,15 @@ async def send_animation( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None,business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVoice' payload = {'chat_id': chat_id} files = None @@ -1007,13 +1035,15 @@ async def send_voice(token, chat_id, voice, caption=None, duration=None, reply_ payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_video_note(token, chat_id, data, duration=None, length=None, reply_markup=None, disable_notification=None, timeout=None, thumbnail=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, allow_paid_broadcast=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendVideoNote' payload = {'chat_id': chat_id} files = None @@ -1055,13 +1085,15 @@ async def send_video_note(token, chat_id, data, duration=None, length=None, rep payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') async def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None, protect_content=None, message_thread_id=None,reply_parameters=None, business_connection_id=None, - message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None): + message_effect_id=None, allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = r'sendAudio' payload = {'chat_id': chat_id} files = None @@ -1109,6 +1141,8 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1116,7 +1150,7 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None, disable_content_type_detection=None, visible_file_name=None, protect_content=None, message_thread_id=None, emoji=None,reply_parameters=None, business_connection_id=None, message_effect_id=None, - allow_paid_broadcast=None, direct_messages_topic_id=None): + allow_paid_broadcast=None, direct_messages_topic_id=None, suggested_post_parameters=None): method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None @@ -1165,6 +1199,8 @@ async def send_data(token, chat_id, data, data_type, reply_markup=None, parse_m payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload, files=files, method='post') @@ -1752,7 +1788,7 @@ async def send_invoice( disable_notification=None, reply_markup=None, provider_data=None, timeout=None, max_tip_amount=None, suggested_tip_amounts=None, protect_content=None, message_thread_id=None, reply_parameters=None, message_effect_id=None, allow_paid_broadcast=None, - direct_messages_topic_id=None): + direct_messages_topic_id=None, suggested_post_parameters=None): """ Use this method to send invoices. On success, the sent Message is returned. :param token: Bot's token (you don't need to fill this) @@ -1843,6 +1879,8 @@ async def send_invoice( payload['allow_paid_broadcast'] = allow_paid_broadcast if direct_messages_topic_id is not None: payload['direct_messages_topic_id'] = direct_messages_topic_id + if suggested_post_parameters is not None: + payload['suggested_post_parameters'] = suggested_post_parameters.to_json() return await _process_request(token, method_url, params=payload) diff --git a/telebot/types.py b/telebot/types.py index b3958ac79..8b983e742 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -12923,3 +12923,64 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj['user']) return cls(**obj) + +class SuggestedPostPrice(JsonSerializable): + """ + Describes the price of a suggested post. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostprice + + :param currency: Currency in which the post will be paid. Currently, must be one of “XTR” for Telegram Stars or “TON” for toncoins + :type currency: :obj:`str` + + :param amount: The amount of the currency that will be paid for the post in the smallest units of the currency, i.e. Telegram Stars or nanotoncoins. Currently, price in Telegram Stars must be between 5 and 100000, and price in nanotoncoins must be between 10000000 and 10000000000000. + :type amount: :obj:`int` + + :return: Instance of the class + :rtype: :class:`SuggestedPostPrice` + """ + def __init__(self, currency: str, amount: int, **kwargs): + self.currency: str = currency + self.amount: int = amount + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = { + 'currency': self.currency, + 'amount': self.amount + } + return data + + +class SuggestedPostParameters(JsonSerializable): + """ + Contains parameters of a post that is being suggested by the bot. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostparameters + + :param price: Optional. Proposed price for the post. If the field is omitted, then the post is unpaid. + :type price: :class:`SuggestedPostPrice` + + :param send_date: Optional. Proposed send date of the post. If specified, then the date must be between 300 second and 2678400 seconds (30 days) in the future. If the field is omitted, then the post can be published at any time within 30 days at the sole discretion of the user who approves it. + :type send_date: :obj:`int` + + :return: Instance of the class + :rtype: :class:`SuggestedPostParameters` + """ + def __init__(self, price: Optional[SuggestedPostPrice] = None, send_date: Optional[int] = None, **kwargs): + self.price: Optional[SuggestedPostPrice] = price + self.send_date: Optional[int] = send_date + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + data = {} + if self.price is not None: + data['price'] = self.price.to_dict() + if self.send_date is not None: + data['send_date'] = self.send_date + return data + From 5bd15376146e0f2da2f950504160cc4dc9cc746f Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 22:37:15 +0500 Subject: [PATCH 465/480] Added the method approveSuggestedPost, allowing bots to approve incoming suggested posts. Added the method declineSuggestedPost, allowing bots to decline incoming suggested posts. --- telebot/__init__.py | 45 +++++++++++++++++++++++++++++++++++++++ telebot/apihelper.py | 14 ++++++++++++ telebot/async_telebot.py | 44 ++++++++++++++++++++++++++++++++++++++ telebot/asyncio_helper.py | 15 +++++++++++++ 4 files changed, 118 insertions(+) diff --git a/telebot/__init__.py b/telebot/__init__.py index ecad66fa8..f62d6ca08 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2008,6 +2008,51 @@ def copy_message( video_start_timestamp=video_start_timestamp, direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters )) + + + def approve_suggested_post(self, chat_id: Union[int, str], message_id: int, send_date: Optional[int]=None) -> bool: + """ + Use this method to approve a suggested post in a direct messages chat. The bot must have the 'can_post_messages' administrator right in the corresponding channel chat. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#approvesuggestedpost + + :param chat_id: Unique identifier for the target direct messages chat + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Identifier of a suggested post message to approve + :type message_id: :obj:`int` + + :param send_date: Point in time (Unix timestamp) when the post is expected to be published; omit if the date has already been specified when the suggested post was created. + If specified, then the date must be not more than 2678400 seconds (30 days) in the future + :type send_date: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.approve_suggested_post(self.token, chat_id, message_id, + send_date=send_date) + + def decline_suggested_post(self, chat_id: Union[int, str], message_id: int, comment: Optional[str]=None) -> bool: + """ + Use this method to decline a suggested post in a direct messages chat. The bot must have + the 'can_manage_direct_messages' administrator right in the corresponding channel chat. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#declinesuggestedpost + + :param chat_id: Unique identifier for the target direct messages chat + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Identifier of a suggested post message to decline + :type message_id: :obj:`int` + + :param comment: Comment for the creator of the suggested post; 0-128 characters + :type comment: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return apihelper.decline_suggested_post(self.token, chat_id, message_id, + comment=comment) def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: diff --git a/telebot/apihelper.py b/telebot/apihelper.py index beb778d06..faee96fce 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1691,6 +1691,20 @@ def edit_message_reply_markup( payload['timeout'] = timeout return _make_request(token, method_url, params=payload, method='post') +def approve_suggested_post(token, chat_id, message_id, send_date=None): + method_url = r'approveSuggestedPost' + payload = {'chat_id': chat_id, 'message_id': message_id} + if send_date is not None: + payload['send_date'] = send_date + return _make_request(token, method_url, params=payload, method='post') + +def decline_suggested_post(token, chat_id, message_id, comment=None): + method_url = r'declineSuggestedPost' + payload = {'chat_id': chat_id, 'message_id': message_id} + if comment is not None: + payload['comment'] = comment + return _make_request(token, method_url, params=payload, method='post') + def delete_message(token, chat_id, message_id, timeout=None): method_url = r'deleteMessage' diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 04325e1c0..c310cf620 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3536,6 +3536,50 @@ async def copy_message( direct_messages_topic_id=direct_messages_topic_id, suggested_post_parameters=suggested_post_parameters ) ) + + async def approve_suggested_post(self, chat_id: Union[int, str], message_id: int, send_date: Optional[int]=None) -> bool: + """ + Use this method to approve a suggested post in a direct messages chat. The bot must have the 'can_post_messages' administrator right in the corresponding channel chat. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#approvesuggestedpost + + :param chat_id: Unique identifier for the target direct messages chat + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Identifier of a suggested post message to approve + :type message_id: :obj:`int` + + :param send_date: Point in time (Unix timestamp) when the post is expected to be published; omit if the date has already been specified when the suggested post was created. + If specified, then the date must be not more than 2678400 seconds (30 days) in the future + :type send_date: :obj:`int` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.approve_suggested_post(self.token, chat_id, message_id, + send_date=send_date) + + async def decline_suggested_post(self, chat_id: Union[int, str], message_id: int, comment: Optional[str]=None) -> bool: + """ + Use this method to decline a suggested post in a direct messages chat. The bot must have + the 'can_manage_direct_messages' administrator right in the corresponding channel chat. Returns True on success. + + Telegram documentation: https://core.telegram.org/bots/api#declinesuggestedpost + + :param chat_id: Unique identifier for the target direct messages chat + :type chat_id: :obj:`int` or :obj:`str` + + :param message_id: Identifier of a suggested post message to decline + :type message_id: :obj:`int` + + :param comment: Comment for the creator of the suggested post; 0-128 characters + :type comment: :obj:`str` + + :return: Returns True on success. + :rtype: :obj:`bool` + """ + return await asyncio_helper.decline_suggested_post(self.token, chat_id, message_id, + comment=comment) async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 05ad2a8a0..074324f71 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1686,6 +1686,21 @@ async def edit_message_reply_markup( payload['timeout'] = timeout return await _process_request(token, method_url, params=payload, method='post') + +async def approve_suggested_post(token, chat_id, message_id, send_date=None): + method_url = r'approveSuggestedPost' + payload = {'chat_id': chat_id, 'message_id': message_id} + if send_date is not None: + payload['send_date'] = send_date + return await _process_request(token, method_url, params=payload, method='post') + + +async def decline_suggested_post(token, chat_id, message_id, comment=None): + method_url = r'declineSuggestedPost' + payload = {'chat_id': chat_id, 'message_id': message_id} + if comment is not None: + payload['comment'] = comment + return await _process_request(token, method_url, params=payload, method='post') async def delete_message(token, chat_id, message_id, timeout=None): method_url = r'deleteMessage' From 181a15218c5ffb58df486b181cde71d2524c8988 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 22:46:02 +0500 Subject: [PATCH 466/480] Added the field can_manage_direct_messages to the classes ChatMemberAdministrator and ChatAdministratorRights. --- telebot/types.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 8b983e742..0e0236271 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -3408,6 +3408,9 @@ class ChatMemberAdministrator(ChatMember): :param can_manage_topics: Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only :type can_manage_topics: :obj:`bool` + :param can_manage_direct_messages: Optional. True, if the administrator can manage direct messages of the channel and decline suggested posts; for channels only + :type can_manage_direct_messages: :obj:`bool` + :param custom_title: Optional. Custom title for this user :type custom_title: :obj:`str` @@ -3417,7 +3420,7 @@ class ChatMemberAdministrator(ChatMember): def __init__(self, user, status, can_be_edited, is_anonymous, can_manage_chat, can_delete_messages, can_manage_video_chats, can_restrict_members, can_promote_members, can_change_info, can_invite_users, can_post_stories, can_edit_stories, can_delete_stories, can_post_messages=None, can_edit_messages=None, - can_pin_messages=None, can_manage_topics=None, custom_title=None, **kwargs): + can_pin_messages=None, can_manage_topics=None, custom_title=None, can_manage_direct_messages=None, **kwargs): super().__init__(user, status, **kwargs) self.can_be_edited: bool = can_be_edited self.is_anonymous: bool = is_anonymous @@ -3436,6 +3439,7 @@ def __init__(self, user, status, can_be_edited, is_anonymous, can_manage_chat, c self.can_pin_messages: Optional[bool] = can_pin_messages self.can_manage_topics: Optional[bool] = can_manage_topics self.custom_title: Optional[str] = custom_title + self.can_manage_direct_messages: Optional[bool] = can_manage_direct_messages @property def can_manage_voice_chats(self): @@ -7903,6 +7907,9 @@ class ChatAdministratorRights(JsonDeserializable, JsonSerializable, Dictionaryab :param can_delete_stories: Optional. True, if the administrator can delete stories of other users :type can_delete_stories: :obj:`bool` + :param can_manage_direct_messages: Optional. True, if the administrator can manage direct messages of the channel and decline suggested posts; for channels only + :type can_manage_direct_messages: :obj:`bool` + :return: Instance of the class :rtype: :class:`telebot.types.ChatAdministratorRights` """ @@ -7919,7 +7926,8 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_post_messages: Optional[bool]=None, can_edit_messages: Optional[bool]=None, can_pin_messages: Optional[bool]=None, can_manage_topics: Optional[bool]=None, can_post_stories: Optional[bool]=None, can_edit_stories: Optional[bool]=None, - can_delete_stories: Optional[bool]=None, **kwargs + can_delete_stories: Optional[bool]=None, can_manage_direct_messages: Optional[bool]=None, + **kwargs ) -> None: self.is_anonymous: bool = is_anonymous @@ -7937,6 +7945,7 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, self.can_post_stories: Optional[bool] = can_post_stories self.can_edit_stories: Optional[bool] = can_edit_stories self.can_delete_stories: Optional[bool] = can_delete_stories + self.can_manage_direct_messages: Optional[bool] = can_manage_direct_messages def to_dict(self): json_dict = { @@ -7963,6 +7972,8 @@ def to_dict(self): json_dict['can_edit_stories'] = self.can_edit_stories if self.can_delete_stories is not None: json_dict['can_delete_stories'] = self.can_delete_stories + if self.can_manage_direct_messages is not None: + json_dict['can_manage_direct_messages'] = self.can_manage_direct_messages return json_dict From 2400f25d77288921394916d2c6726a092ce6f960 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 22:57:43 +0500 Subject: [PATCH 467/480] Added the parameter can_manage_direct_messages to the method promoteChatMember. --- telebot/__init__.py | 10 ++++++++-- telebot/apihelper.py | 4 +++- telebot/async_telebot.py | 10 ++++++++-- telebot/asyncio_helper.py | 5 ++++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index f62d6ca08..679afc311 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -4416,7 +4416,8 @@ def promote_chat_member( can_manage_topics: Optional[bool]=None, can_post_stories: Optional[bool]=None, can_edit_stories: Optional[bool]=None, - can_delete_stories: Optional[bool]=None) -> bool: + can_delete_stories: Optional[bool]=None, + can_manage_direct_messages: Optional[bool]=None) -> bool: """ Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -4486,6 +4487,10 @@ def promote_chat_member( :param can_delete_stories: Pass True if the administrator can delete the channel's stories :type can_delete_stories: :obj:`bool` + :param can_manage_direct_messages: Pass True if the administrator can manage direct messages + within the channel and decline suggested posts; for channels only + :type can_manage_direct_messages: :obj:`bool` + :return: True on success. :rtype: :obj:`bool` """ @@ -4502,7 +4507,8 @@ def promote_chat_member( is_anonymous=is_anonymous, can_manage_chat=can_manage_chat, can_manage_video_chats=can_manage_video_chats, can_manage_topics=can_manage_topics, can_post_stories=can_post_stories, can_edit_stories=can_edit_stories, - can_delete_stories=can_delete_stories) + can_delete_stories=can_delete_stories, can_manage_direct_messages=can_manage_direct_messages, + ) def set_chat_administrator_custom_title( diff --git a/telebot/apihelper.py b/telebot/apihelper.py index faee96fce..68f2418da 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -1257,7 +1257,7 @@ def promote_chat_member( can_restrict_members=None, can_pin_messages=None, can_promote_members=None, is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None, can_manage_topics=None, can_post_stories=None, can_edit_stories=None, - can_delete_stories=None): + can_delete_stories=None, can_manage_direct_messages=None): method_url = 'promoteChatMember' payload = {'chat_id': chat_id, 'user_id': user_id} if can_change_info is not None: @@ -1290,6 +1290,8 @@ def promote_chat_member( payload['can_edit_stories'] = can_edit_stories if can_delete_stories is not None: payload['can_delete_stories'] = can_delete_stories + if can_manage_direct_messages is not None: + payload['can_manage_direct_messages'] = can_manage_direct_messages return _make_request(token, method_url, params=payload, method='post') diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index c310cf620..bc01a012e 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5939,7 +5939,8 @@ async def promote_chat_member( can_manage_topics: Optional[bool]=None, can_post_stories: Optional[bool]=None, can_edit_stories: Optional[bool]=None, - can_delete_stories: Optional[bool]=None) -> bool: + can_delete_stories: Optional[bool]=None, + can_manage_direct_messages: Optional[bool]=None) -> bool: """ Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. @@ -6009,6 +6010,10 @@ async def promote_chat_member( :param can_delete_stories: Pass True if the administrator can delete the channel's stories :type can_delete_stories: :obj:`bool` + :param can_manage_direct_messages: Pass True if the administrator can manage direct messages + within the channel and decline suggested posts; for channels only + :type can_manage_direct_messages: :obj:`bool` + :return: True on success. :rtype: :obj:`bool` """ @@ -6023,7 +6028,8 @@ async def promote_chat_member( can_edit_messages, can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, is_anonymous, can_manage_chat, can_manage_video_chats, can_manage_topics, - can_post_stories, can_edit_stories, can_delete_stories) + can_post_stories, can_edit_stories, can_delete_stories, can_manage_direct_messages=can_manage_direct_messages + ) async def set_chat_administrator_custom_title( self, chat_id: Union[int, str], user_id: int, custom_title: str) -> bool: diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 074324f71..f127f316f 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -1252,7 +1252,8 @@ async def promote_chat_member( can_edit_messages=None, can_delete_messages=None, can_invite_users=None, can_restrict_members=None, can_pin_messages=None, can_promote_members=None, is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None, can_manage_topics=None, - can_post_stories=None, can_edit_stories=None, can_delete_stories=None): + can_post_stories=None, can_edit_stories=None, can_delete_stories=None, + can_manage_direct_messages=None): method_url = 'promoteChatMember' payload = {'chat_id': chat_id, 'user_id': user_id} if can_change_info is not None: @@ -1285,6 +1286,8 @@ async def promote_chat_member( payload['can_edit_stories'] = can_edit_stories if can_delete_stories is not None: payload['can_delete_stories'] = can_delete_stories + if can_manage_direct_messages is not None: + payload['can_manage_direct_messages'] = can_manage_direct_messages return await _process_request(token, method_url, params=payload, method='post') From 6f88714091068a9b3dde476ccc56c96beec32d23 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 22:59:14 +0500 Subject: [PATCH 468/480] Added the field is_paid_post to the class Message, which can be used to identify paid posts. Such posts must not be deleted for 24 hours to receive the payment. --- telebot/types.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telebot/types.py b/telebot/types.py index 0e0236271..54bac6dae 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -997,6 +997,10 @@ class Message(JsonDeserializable): as an away or a greeting business message, or as a scheduled message :type is_from_offline: :obj:`bool` + :param is_paid_post: Optional. True, if the message is a paid post. Note that such posts must not be + deleted for 24 hours to receive the payment and can't be edited. + :type is_paid_post: :obj:`bool` + :param media_group_id: Optional. The unique identifier of a media message group this message belongs to :type media_group_id: :obj:`str` @@ -1504,6 +1508,8 @@ def de_json(cls, json_string): opts['reply_to_checklist_task_id'] = obj['reply_to_checklist_task_id'] if 'direct_messages_topic' in obj: opts['direct_messages_topic'] = DirectMessagesTopic.de_json(obj['direct_messages_topic']) + if 'is_paid_post' in obj: + opts['is_paid_post'] = obj['is_paid_post'] return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1632,6 +1638,7 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.direct_message_price_changed: Optional[DirectMessagePriceChanged] = None self.reply_to_checklist_task_id: Optional[int] = None self.direct_messages_topic: Optional[DirectMessagesTopic] = None + self.is_paid_post: Optional[bool] = None for key in options: setattr(self, key, options[key]) From 5ab505630169065d69852fa70e8499627e831a21 Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 23:13:08 +0500 Subject: [PATCH 469/480] Rest classes added --- telebot/types.py | 237 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 235 insertions(+), 2 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 54bac6dae..33cf8dba6 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1022,6 +1022,10 @@ class Message(JsonDeserializable): if it is a text message and link preview options were changed :type link_preview_options: :class:`telebot.types.LinkPreviewOptions` + :param suggested_post_info: Optional. Information about suggested post parameters if the message is a suggested post + in a channel direct messages chat. If the message is an approved or declined suggested post, then it can't be edited. + :type suggested_post_info: :class:`telebot.types.SuggestedPostInfo` + :param effect_id: Optional. Unique identifier of the message effect added to the message :type effect_id: :obj:`str` @@ -1226,6 +1230,21 @@ class Message(JsonDeserializable): :param paid_message_price_changed: Optional. Service message: the price for paid messages has changed in the chat :type paid_message_price_changed: :class:`telebot.types.PaidMessagePriceChanged` + :param suggested_post_approved: Optional. Service message: a suggested post was approved + :type suggested_post_approved: :class:`telebot.types.SuggestedPostApproved + + :param suggested_post_approval_failed: Optional. Service message: approval of a suggested post has failed + :type suggested_post_approval_failed: :class:`telebot.types.SuggestedPost + + :param suggested_post_declined: Optional. Service message: a suggested post was declined + :type suggested_post_declined: :class:`telebot.types.SuggestedPostDecl + + :param suggested_post_paid: Optional. Service message: payment for a suggested post was received + :type suggested_post_paid: :class:`telebot.types.SuggestedPostPaid` + + :param suggested_post_refunded: Optional. Service message: payment for a suggested post was refunded + :type suggested_post_refunded: :class:`telebot.types.SuggestedPostRefunded` + :param video_chat_scheduled: Optional. Service message: video chat scheduled :type video_chat_scheduled: :class:`telebot.types.VideoChatScheduled` @@ -1510,6 +1529,24 @@ def de_json(cls, json_string): opts['direct_messages_topic'] = DirectMessagesTopic.de_json(obj['direct_messages_topic']) if 'is_paid_post' in obj: opts['is_paid_post'] = obj['is_paid_post'] + if 'suggested_post_info' in obj: + opts['suggested_post_info'] = SuggestedPostInfo.de_json(obj['suggested_post_info']) + content_type = 'suggested_post_info' + if 'suggested_post_approved' in obj: + opts['suggested_post_approved'] = SuggestedPostApproved.de_json(obj['suggested_post_approved']) + content_type = 'suggested_post_approved' + if 'suggested_post_approval_failed' in obj: + opts['suggested_post_approval_failed'] = SuggestedPostApprovalFailed.de_json(obj['suggested_post_approval_failed']) + content_type = 'suggested_post_approval_failed' + if 'suggested_post_declined' in obj: + opts['suggested_post_declined'] = SuggestedPostDeclined.de_json(obj['suggested_post_declined']) + content_type = 'suggested_post_declined' + if 'suggested_post_paid' in obj: + opts['suggested_post_paid'] = SuggestedPostPaid.de_json(obj['suggested_post_paid']) + content_type = 'suggested_post_paid' + if 'suggested_post_refunded' in obj: + opts['suggested_post_refunded'] = SuggestedPostRefunded.de_json(obj['suggested_post_refunded']) + content_type = 'suggested_post_refunded' return cls(message_id, from_user, date, chat, content_type, opts, json_string) @@ -1639,6 +1676,12 @@ def __init__(self, message_id, from_user, date, chat, content_type, options, jso self.reply_to_checklist_task_id: Optional[int] = None self.direct_messages_topic: Optional[DirectMessagesTopic] = None self.is_paid_post: Optional[bool] = None + self.suggested_post_info: Optional[SuggestedPostInfo] = None + self.suggested_post_approved: Optional[SuggestedPostApproved] = None + self.suggested_post_approval_failed: Optional[SuggestedPostApprovalFailed] = None + self.suggested_post_declined: Optional[SuggestedPostDeclined] = None + self.suggested_post_paid: Optional[SuggestedPostPaid] = None + self.suggested_post_refunded: Optional[SuggestedPostRefunded] = None for key in options: setattr(self, key, options[key]) @@ -12942,7 +12985,7 @@ def de_json(cls, json_string): return cls(**obj) -class SuggestedPostPrice(JsonSerializable): +class SuggestedPostPrice(JsonSerializable, JsonDeserializable): """ Describes the price of a suggested post. @@ -12969,7 +13012,13 @@ def to_dict(self): 'currency': self.currency, 'amount': self.amount } - return data + return data + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + return cls(**obj) class SuggestedPostParameters(JsonSerializable): @@ -13002,3 +13051,187 @@ def to_dict(self): data['send_date'] = self.send_date return data + +class SuggestedPostInfo(JsonDeserializable): + """ + Contains information about a suggested post. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostinfo + + :param state: State of the suggested post. Currently, it can be one of “pending”, “approved”, “declined”. + :type state: :obj:`str` + + :param price: Optional. Proposed price of the post. If the field is omitted, then the post is unpaid. + :type price: :class:`SuggestedPostPrice` + + :param send_date: Optional. Proposed send date of the post. If the field is omitted, then the post can be published at any time within 30 days at the sole discretion of the user or administrator who approves it. + :type send_date: :obj:`int` + + :return: Instance of the class + :rtype: :class:`SuggestedPostInfo` + """ + def __init__(self, state: str, price: Optional[SuggestedPostPrice] + = None, send_date: Optional[int] = None, **kwargs): + self.state: str = state + self.price: Optional[SuggestedPostPrice] = price + self.send_date: Optional[int] = send_date + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'price' in obj: + obj['price'] = SuggestedPostPrice.de_json(obj['price']) + return cls(**obj) + + +class SuggestedPostApproved(JsonDeserializable): + """ + Describes a service message about the approval of a suggested post. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostapproved + + :param suggested_post_message: Optional. Message containing the suggested post. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type suggested_post_message: :class:`Message` + + :param price: Optional. Amount paid for the post + :type price: :class:`SuggestedPostPrice` + + :param send_date: Optional. Date when the post will be published + :type send_date: int + + :return: Instance of the class + :rtype: :class:`SuggestedPostApproved` + """ + def __init__(self, suggested_post_message: Optional[Message] = None, + price: Optional[SuggestedPostPrice] = None, + send_date: Optional[int] = None, **kwargs): + self.suggested_post_message: Optional[Message] = suggested_post_message + self.price: Optional[SuggestedPostPrice] = price + self.send_date: Optional[int] = send_date + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'suggested_post_message' in obj: + obj['suggested_post_message'] = Message.de_json(obj['suggested_post_message']) + if 'price' in obj: + obj['price'] = SuggestedPostPrice.de_json(obj['price']) + return cls(**obj) + +class SuggestedPostApprovalFailed(JsonDeserializable): + """ + Describes a service message about the failed approval of a suggested post. + Currently, only caused by insufficient user funds at the time of approval. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostapprovalfailed + + :param suggested_post_message: Optional. Message containing the suggested post whose approval has failed. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type suggested_post_message: :class:`Message` + + :return: Instance of the class + :rtype: :class:`SuggestedPostApprovalFailed` + """ + def __init__(self, suggested_post_message: Optional[Message] = None, **kwargs): + self.suggested_post_message: Optional[Message] = suggested_post_message + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'suggested_post_message' in obj: + obj['suggested_post_message'] = Message.de_json(obj['suggested_post_message']) + return cls(**obj) + +class SuggestedPostDeclined(JsonDeserializable): + """ + Describes a service message about the rejection of a suggested post. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostdeclined + + :param suggested_post_message: Optional. Message containing the suggested post. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type suggested_post_message: :class:`Message` + + :return: Instance of the class + :rtype: :class:`SuggestedPostDeclined` + """ + def __init__(self, suggested_post_message: Optional[Message] = None, comment: Optional[str] = None, **kwargs): + self.suggested_post_message: Optional[Message] = suggested_post_message + self.comment: Optional[str] = comment + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'suggested_post_message' in obj: + obj['suggested_post_message'] = Message.de_json(obj['suggested_post_message']) + return cls(**obj) + +class SuggestedPostPaid(JsonDeserializable): + """ + Describes a service message about a successful payment for a suggested post. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostpaid + + :param suggested_post_message: Optional. Message containing the suggested post. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type suggested_post_message: :class:`Message` + + :param currency: Currency in which the payment was made. Currently, one of “XTR” for Telegram Stars or “TON” for toncoins + :type currency: :obj:`str` + + :param amount: Optional. The amount of the currency that was received by the channel in nanotoncoins; for payments in toncoins only + :type amount: :obj:`int` + + :param star_amount: Optional. The amount of Telegram Stars that was received by the channel; for payments in Telegram Stars only + :type star_amount: :class:`StarAmount` + + :return: Instance of the class + :rtype: :class:`SuggestedPostPaid` + """ + def __init__(self, currency: str,suggested_post_message: Optional[Message] = None, + amount: Optional[int] = None, + star_amount: Optional[StarAmount] = None, **kwargs): + self.suggested_post_message: Optional[Message] = suggested_post_message + self.currency: str = currency + self.amount: Optional[int] = amount + self.star_amount: Optional[StarAmount] = star_amount + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'suggested_post_message' in obj: + obj['suggested_post_message'] = Message.de_json(obj['suggested_post_message']) + if 'star_amount' in obj: + obj['star_amount'] = StarAmount.de_json(obj['star_amount']) + return cls(**obj) + +class SuggestedPostRefunded(JsonDeserializable): + """ + Describes a service message about a payment refund for a suggested post. + + Telegram documentation: https://core.telegram.org/bots/api#suggestedpostrefunded + + :param suggested_post_message: Optional. Message containing the suggested post. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. + :type suggested_post_message: :class:`Message` + + :param reason: Reason for the refund. Currently, one of “post_deleted” if the post was deleted within 24 hours of being posted or removed from scheduled messages without being posted, or “payment_refunded” if the payer refunded their payment. + :type reason: :obj:`str` + + :return: Instance of the class + :rtype: :class:`SuggestedPostRefunded` + """ + def __init__(self, suggested_post_message: Optional[Message] = None, reason: Optional[str] = None, **kwargs): + self.suggested_post_message: Optional[Message] = suggested_post_message + self.reason: Optional[str] = reason + + @classmethod + def de_json(cls, json_string): + if json_string is None: return None + obj = cls.check_json(json_string) + if 'suggested_post_message' in obj: + obj['suggested_post_message'] = Message.de_json(obj['suggested_post_message']) + return cls(**obj) + + + \ No newline at end of file From 3fad50de693d51356af1a49671f41ddf02c324ea Mon Sep 17 00:00:00 2001 From: _run Date: Sun, 17 Aug 2025 23:13:41 +0500 Subject: [PATCH 470/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a67b7d78..29764fb3c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

A simple, but extensible Python implementation for the Telegram Bot API.

Both synchronous and asynchronous.

-##

Supported Bot API version: Supported Bot API version +##

Supported Bot API version: Supported Bot API version

Official documentation

Official ru documentation

From 95d43c82df1f265580773166b0ca030c0de882d8 Mon Sep 17 00:00:00 2001 From: All-The-Foxes <116322192+All-The-Foxes@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:06:21 -0400 Subject: [PATCH 471/480] Default to None for filter func in inline_handler --- telebot/async_telebot.py | 896 +++++++++++++++++++-------------------- 1 file changed, 448 insertions(+), 448 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index fe8013135..e9f18d157 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -26,7 +26,7 @@ logger = logging.getLogger('TeleBot') REPLY_MARKUP_TYPES = Union[ - types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup, + types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup, types.ReplyKeyboardRemove, types.ForceReply] @@ -76,7 +76,7 @@ class AsyncTeleBot: from telebot.async_telebot import AsyncTeleBot bot = AsyncTeleBot('token') # get token from @BotFather - # now you can register other handlers/update listeners, + # now you can register other handlers/update listeners, # and use bot methods. # Remember to use async/await keywords when necessary. @@ -114,7 +114,7 @@ class AsyncTeleBot: :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Default value for allow_sending_without_reply, defaults to None :type allow_sending_without_reply: :obj:`bool`, optional - + :param colorful_logs: Outputs colorful logs :type colorful_logs: :obj:`bool`, optional @@ -134,7 +134,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ allow_sending_without_reply: Optional[bool]=None, colorful_logs: Optional[bool]=False, validate_token: Optional[bool]=True) -> None: - + # update-related self.token = token self.offset = offset @@ -148,7 +148,7 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ raise ImportError( 'Install coloredlogs module to use colorful_logs option.' ) - + # properties self.parse_mode = parse_mode self.disable_web_page_preview = disable_web_page_preview @@ -194,9 +194,9 @@ def __init__(self, token: str, parse_mode: Optional[str]=None, offset: Optional[ if validate_token: util.validate_token(self.token) - + self.bot_id: Union[int, None] = util.extract_bot_id(self.token) # subject to change, unspecified - + @property def user(self): @@ -237,7 +237,7 @@ async def get_updates(self, offset: Optional[int]=None, limit: Optional[int]=Non :return: An Array of Update objects is returned. :rtype: :obj:`list` of :class:`telebot.types.Update` - """ + """ json_updates = await asyncio_helper.get_updates(self.token, offset, limit, timeout, allowed_updates, request_timeout) return [types.Update.de_json(ju) for ju in json_updates] @@ -255,7 +255,7 @@ def _setup_change_detector(self, path_to_watch: str) -> None: if path is None: # Make it possible to specify --path argument to the script path = sys.argv[sys.argv.index('--path') + 1] if '--path' in sys.argv else '.' - + self.event_observer = Observer() self.event_observer.schedule(self.event_handler, path, recursive=True) self.event_observer.start() @@ -268,7 +268,7 @@ async def polling(self, non_stop: bool=True, skip_pending=False, interval: int=0 This allows the bot to retrieve Updates automagically and notify listeners and message handlers accordingly. Warning: Do not call this function more than once! - + Always gets updates. .. note:: @@ -277,7 +277,7 @@ async def polling(self, non_stop: bool=True, skip_pending=False, interval: int=0 :param non_stop: Do not stop polling when an ApiException occurs. :type non_stop: :obj:`bool` - + :param skip_pending: skip old updates :type skip_pending: :obj:`bool` @@ -286,17 +286,17 @@ async def polling(self, non_stop: bool=True, skip_pending=False, interval: int=0 :param timeout: Request connection timeout :type timeout: :obj:`int` - + :param request_timeout: Timeout in seconds for get_updates(Defaults to None) :type request_timeout: :obj:`int` :param allowed_updates: A list of the update types you want your bot to receive. - For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. - See util.update_types for a complete list of available update types. - Specify an empty list to receive all update types except chat_member (default). + For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. + See util.update_types for a complete list of available update types. + Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - - Please note that this parameter doesn't affect updates created before the call to the get_updates, + + Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` @@ -308,7 +308,7 @@ async def polling(self, non_stop: bool=True, skip_pending=False, interval: int=0 :param path_to_watch: Path to watch for changes. Defaults to current directory :type path_to_watch: :obj:`str` - + :return: """ if none_stop is not None: @@ -346,12 +346,12 @@ async def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Option :type logger_level: :obj:`int` :param allowed_updates: A list of the update types you want your bot to receive. - For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. - See util.update_types for a complete list of available update types. - Specify an empty list to receive all update types except chat_member (default). + For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. + See util.update_types for a complete list of available update types. + Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - - Please note that this parameter doesn't affect updates created before the call to the get_updates, + + Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` @@ -402,7 +402,7 @@ def __hide_token(self, message: str) -> str: return message.replace(code, "*" * len(code)) else: return message - + async def _handle_error_interval(self, error_interval: float): logger.debug('Waiting for %s seconds before retrying', error_interval) await asyncio.sleep(error_interval) @@ -439,7 +439,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: logger.warning("Setting non_stop to False will stop polling on API and system exceptions.") self._user = await self.get_me() - + logger.info('Starting your bot with username: [@%s]', self.user.username) self._polling = True @@ -469,7 +469,7 @@ async def _process_polling(self, non_stop: bool=False, interval: int=0, timeout: if non_stop: error_interval = await self._handle_error_interval(error_interval) - + if non_stop or handled: continue else: @@ -837,7 +837,7 @@ async def process_new_poll_answer(self, poll_answers): :meta private: """ await self._process_updates(self.poll_answer_handlers, poll_answers, 'poll_answer') - + async def process_new_my_chat_member(self, my_chat_members): """ :meta private: @@ -885,7 +885,7 @@ async def process_new_edited_business_message(self, new_edited_business_messages :meta private: """ await self._process_updates(self.edited_business_message_handlers, new_edited_business_messages, 'edited_business_message') - + async def process_new_deleted_business_messages(self, new_deleted_business_messages): """ :meta private: @@ -906,7 +906,7 @@ async def _get_middlewares(self, update_type): middlewares = [middleware for middleware in self.middlewares if update_type in middleware.update_types] return middlewares return None - + async def __notify_update(self, new_messages): if len(self.update_listener) == 0: return @@ -945,7 +945,7 @@ async def update_listener(new_messages): print(message.text) # Prints message text bot.set_update_listener(update_listener) - + :return: None """ self.update_listener.append(func) @@ -1033,7 +1033,7 @@ def setup_middleware(self, middleware: BaseMiddleware): :param middleware: Middleware-class. :type middleware: :class:`telebot.asyncio_handler_backends.BaseMiddleware` - + :return: None """ if not hasattr(middleware, 'update_types'): @@ -1106,7 +1106,7 @@ async def default_command(message): :param func: Optional lambda function. The lambda receives the message to test as the first parameter. It must return True if the command should handle the message. - + :param content_types: Supported message content types. Must be a list. Defaults to ['text']. :type content_types: :obj:`list` of :obj:`str` @@ -1147,7 +1147,7 @@ def add_message_handler(self, handler_dict): """ Adds a message handler. Note that you should use register_message_handler to add message_handler. - + :meta private: :param handler_dict: @@ -1371,7 +1371,7 @@ def add_channel_post_handler(self, handler_dict): :return: """ self.channel_post_handlers.append(handler_dict) - + def register_channel_post_handler(self, callback: Callable[[Any], Awaitable], content_types: Optional[List[str]]=None, commands: Optional[List[str]]=None, regexp: Optional[str]=None, func: Optional[Callable]=None, pass_bot: Optional[bool]=False, **kwargs): """ @@ -1535,7 +1535,7 @@ def decorator(handler): return handler return decorator - + def add_message_reaction_handler(self, handler_dict): """ Adds message reaction handler. @@ -1560,7 +1560,7 @@ def register_message_reaction_handler(self, callback: Callable[[Any], Awaitable] :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) :type pass_bot: :obj:`bool` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -1587,7 +1587,7 @@ def decorator(handler): return handler return decorator - + def add_message_reaction_count_handler(self, handler_dict): """ Adds message reaction count handler @@ -1612,7 +1612,7 @@ def register_message_reaction_count_handler(self, callback: Callable[[Any], Awai :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) :type pass_bot: :obj:`bool` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -1621,7 +1621,7 @@ def register_message_reaction_count_handler(self, callback: Callable[[Any], Awai self.add_message_reaction_count_handler(handler_dict) - def inline_handler(self, func, **kwargs): + def inline_handler(self, func=None, **kwargs): """ Handles new incoming inline query. As a parameter to the decorator function, it passes :class:`telebot.types.InlineQuery` object. @@ -1681,7 +1681,7 @@ def chosen_inline_handler(self, func, **kwargs): :param func: Function executed as a filter :type func: :obj:`function` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -1735,7 +1735,7 @@ def callback_query_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ @@ -1787,7 +1787,7 @@ def shipping_query_handler(self, func, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ @@ -1861,7 +1861,7 @@ def add_pre_checkout_query_handler(self, handler_dict): :return: """ self.pre_checkout_query_handlers.append(handler_dict) - + def register_pre_checkout_query_handler(self, callback: Callable[[Any], Awaitable], func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers pre-checkout request handler. @@ -1896,9 +1896,9 @@ def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) self.add_purchased_paid_media_handler(handler_dict) return handler - + return decorator - + def add_purchased_paid_media_handler(self, handler_dict): """ Adds a purchased paid media handler @@ -1917,7 +1917,7 @@ def register_purchased_paid_media_handler(self, callback: Callable, func: Callab :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -1992,7 +1992,7 @@ def poll_answer_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ @@ -2152,7 +2152,7 @@ def chat_join_request_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ @@ -2198,7 +2198,7 @@ def register_chat_join_request_handler(self, callback: Callable[[Any], Awaitable def chat_boost_handler(self, func=None, **kwargs): """ - Handles new incoming chat boost state. + Handles new incoming chat boost state. it passes :class:`telebot.types.ChatBoostUpdated` object. :param func: Function executed as a filter @@ -2213,7 +2213,7 @@ def decorator(handler): return handler return decorator - + def add_chat_boost_handler(self, handler_dict): """ Adds a chat_boost handler. @@ -2232,7 +2232,7 @@ def register_chat_boost_handler(self, callback: Callable, func: Optional[Callabl :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -2247,7 +2247,7 @@ def register_chat_boost_handler(self, callback: Callable, func: Optional[Callabl def removed_chat_boost_handler(self, func=None, **kwargs): """ - Handles new incoming chat boost state. + Handles new incoming chat boost state. it passes :class:`telebot.types.ChatBoostRemoved` object. :param func: Function executed as a filter @@ -2262,7 +2262,7 @@ def decorator(handler): return handler return decorator - + def add_removed_chat_boost_handler(self, handler_dict): """ Adds a removed_chat_boost handler. @@ -2281,7 +2281,7 @@ def register_removed_chat_boost_handler(self, callback: Callable, func: Optional :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -2309,9 +2309,9 @@ def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) self.add_business_connection_handler(handler_dict) return handler - + return decorator - + def add_business_connection_handler(self, handler_dict): """ Adds a business_connection handler. @@ -2426,7 +2426,7 @@ def decorator(handler): return handler return decorator - + def add_business_message_handler(self, handler_dict): """ Adds a business_message handler. @@ -2476,8 +2476,8 @@ def register_business_message_handler(self, pass_bot=pass_bot,**kwargs) self.add_business_message_handler(handler_dict) - - + + def edited_business_message_handler(self, commands=None, regexp=None, func=None, content_types=None, **kwargs): """ @@ -2534,7 +2534,7 @@ def add_edited_business_message_handler(self, handler_dict): """ Adds the edit message handler Note that you should use register_edited_business_message_handler to add edited_business_message_handler to the bot. - + :meta private: :param handler_dict: @@ -2594,7 +2594,7 @@ def register_edited_business_message_handler(self, callback: Callable, content_t **kwargs) self.add_edited_business_message_handler(handler_dict) - + def deleted_business_messages_handler(self, func=None, **kwargs): """ Handles new incoming deleted messages state. @@ -2611,9 +2611,9 @@ def decorator(handler): self.add_deleted_business_messages_handler(handler_dict) return handler - + return decorator - + def add_deleted_business_messages_handler(self, handler_dict): """ Adds a deleted_business_messages handler. @@ -2670,7 +2670,7 @@ async def skip_updates(self): return True # all methods begin here - + async def get_me(self) -> types.User: """ Returns basic information about the bot in form of a User object. @@ -2683,9 +2683,9 @@ async def get_me(self) -> types.User: async def get_file(self, file_id: Optional[str]) -> types.File: """ Use this method to get basic info about a file and prepare it for downloading. - For the moment, bots can download files of up to 20MB in size. - On success, a File object is returned. - It is guaranteed that the link will be valid for at least 1 hour. + For the moment, bots can download files of up to 20MB in size. + On success, a File object is returned. + It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can be requested by calling get_file again. Telegram documentation: https://core.telegram.org/bots/api#getfile @@ -2715,7 +2715,7 @@ async def download_file(self, file_path: Optional[str]) -> bytes: :param file_path: Path where the file should be downloaded. :type file_path: str - + :return: bytes :rtype: :obj:`bytes` """ @@ -2723,11 +2723,11 @@ async def download_file(self, file_path: Optional[str]) -> bytes: async def log_out(self) -> bool: """ - Use this method to log out from the cloud Bot API server before launching the bot locally. + Use this method to log out from the cloud Bot API server before launching the bot locally. You MUST log out the bot before running it locally, otherwise there is no guarantee that the bot will receive updates. - After a successful call, you can immediately log in on a local server, - but will not be able to log in back to the cloud Bot API server for 10 minutes. + After a successful call, you can immediately log in on a local server, + but will not be able to log in back to the cloud Bot API server for 10 minutes. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#logout @@ -2736,13 +2736,13 @@ async def log_out(self) -> bool: :rtype: :obj:`bool` """ return await asyncio_helper.log_out(self.token) - + async def close(self) -> bool: """ - Use this method to close the bot instance before moving it from one local server to another. + Use this method to close the bot instance before moving it from one local server to another. You need to delete the webhook before calling this method to ensure that the bot isn't launched again after server restart. - The method will return error 429 in the first 10 minutes after the bot is launched. + The method will return error 429 in the first 10 minutes after the bot is launched. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#close @@ -2790,15 +2790,15 @@ async def set_webhook(self, url: Optional[str]=None, certificate: Optional[Union Defaults to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput, defaults to None :type max_connections: :obj:`int`, optional - + :param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - + Please note that this parameter doesn't affect updates created before the call to the setWebhook, so unwanted updates may be received for a short period of time. Defaults to None - + :type allowed_updates: :obj:`list`, optional :param ip_address: The fixed IP address which will be used to send webhook requests instead of the IP address @@ -2941,7 +2941,7 @@ async def get_webhook_info(self, timeout: Optional[int]=None) -> types.WebhookIn async def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: """ - Use this method to change the chosen reactions on a message. + 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. Returns True on success. @@ -2965,7 +2965,7 @@ async def set_message_reaction(self, chat_id: Union[int, str], message_id: int, result = await asyncio_helper.set_message_reaction(self.token, chat_id, message_id, reaction, is_big) return result - async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, + async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, limit: Optional[int]=None) -> types.UserProfilePhotos: """ Use this method to get a list of profile pictures for a user. @@ -2988,7 +2988,7 @@ async def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None """ result = await asyncio_helper.get_user_profile_photos(self.token, user_id, offset, limit) return types.UserProfilePhotos.de_json(result) - + async def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Optional[str]=None, emoji_status_expiration_date: Optional[int]=None) -> bool: """ Use this method to change the emoji status for a given user that previously allowed the bot to manage their emoji status via the Mini App method requestEmojiStatusAccess. @@ -3045,7 +3045,7 @@ async def get_chat_administrators(self, chat_id: Union[int, str]) -> List[types. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. - Telegram documentation: https://core.telegram.org/bots/api#getchatadministrators + Telegram documentation: https://core.telegram.org/bots/api#getchatadministrators :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) @@ -3075,7 +3075,7 @@ async def get_chat_members_count(self, chat_id: Union[int, str]) -> int: """ result = await asyncio_helper.get_chat_member_count(self.token, chat_id) return result - + async def get_chat_member_count(self, chat_id: Union[int, str]) -> int: """ Use this method to get the number of members in a chat. @@ -3096,7 +3096,7 @@ async def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#setchatstickerset :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -3116,7 +3116,7 @@ async def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletechatstickerset :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -3132,7 +3132,7 @@ async def answer_web_app_query(self, web_app_query_id: str, result: types.Inline """ Use this method to set the result of an interaction with a Web App and send a corresponding message on behalf of the user to the chat from which - the query originated. + the query originated. On success, a SentWebAppMessage object is returned. Telegram Documentation: https://core.telegram.org/bots/api#answerwebappquery @@ -3182,7 +3182,7 @@ async def save_prepared_inline_message(self, user_id: int, result: types.InlineQ async def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatMember: """ Use this method to get information about a member of a chat. Returns a ChatMember object on success. - + Telegram documentation: https://core.telegram.org/bots/api#getchatmember :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -3198,13 +3198,13 @@ async def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types return types.ChatMember.de_json(result) async def send_message( - self, chat_id: Union[int, str], text: str, - parse_mode: Optional[str]=None, + self, chat_id: Union[int, str], text: str, + parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, - disable_web_page_preview: Optional[bool]=None, - disable_notification: Optional[bool]=None, + disable_web_page_preview: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, @@ -3218,7 +3218,7 @@ async def send_message( Use this method to send text messages. Warning: Do not send more than about 4096 characters each message, otherwise you'll risk an HTTP 414 error. - If you must send more than 4096 characters, + If you must send more than 4096 characters, use the `split_string` or `smart_split` function in util.py. Telegram documentation: https://core.telegram.org/bots/api#sendmessage @@ -3283,11 +3283,11 @@ async def send_message( disable_web_page_preview = self.disable_web_page_preview if (disable_web_page_preview is None) else disable_web_page_preview disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -3308,7 +3308,7 @@ async def send_message( if disable_web_page_preview is not None: # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") - + if link_preview_options: # show a conflict warning logger.warning("Both 'link_preview_options' and 'disable_web_page_preview' parameters are set: conflicting, 'disable_web_page_preview' is deprecated") @@ -3334,7 +3334,7 @@ async def send_message( message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def forward_message( - self, chat_id: Union[int, str], from_chat_id: Union[int, str], + self, chat_id: Union[int, str], from_chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, @@ -3359,7 +3359,7 @@ async def forward_message( :param video_start_timestamp: New start timestamp for the forwarded video in the message :type video_start_timestamp: :obj:`int` - + :param protect_content: Protects the contents of the forwarded message from forwarding and saving :type protect_content: :obj:`bool` @@ -3381,17 +3381,17 @@ async def forward_message( timeout=timeout, message_thread_id=message_thread_id, video_start_timestamp=video_start_timestamp)) async def copy_message( - self, chat_id: Union[int, str], - from_chat_id: Union[int, str], - message_id: int, - caption: Optional[str]=None, - parse_mode: Optional[str]=None, + self, chat_id: Union[int, str], + from_chat_id: Union[int, str], + message_id: int, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, @@ -3450,7 +3450,7 @@ async def copy_message( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -3460,7 +3460,7 @@ async def copy_message( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` - + :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` """ @@ -3470,7 +3470,7 @@ async def copy_message( if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -3496,7 +3496,7 @@ async def copy_message( message_thread_id=message_thread_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, video_start_timestamp=video_start_timestamp)) - async def delete_message(self, chat_id: Union[int, str], message_id: int, + async def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: """ Use this method to delete a message, including service messages, with the following limitations: @@ -3524,10 +3524,10 @@ async def delete_message(self, chat_id: Union[int, str], message_id: int, :rtype: :obj:`bool` """ return await asyncio_helper.delete_message(self.token, chat_id, message_id, timeout) - + async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ - Use this method to delete multiple messages simultaneously. + Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they are skipped. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#deletemessages @@ -3542,7 +3542,7 @@ async def delete_messages(self, chat_id: Union[int, str], message_ids: List[int] """ return await asyncio_helper.delete_messages(self.token, chat_id, message_ids) - + async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: """ @@ -3578,7 +3578,7 @@ async def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[s protect_content = self.protect_content if (protect_content is None) else protect_content result = await asyncio_helper.forward_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, protect_content) return [types.MessageID.de_json(message_id) for message_id in result] - + async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: @@ -3619,7 +3619,7 @@ async def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, result = await asyncio_helper.copy_messages(self.token, chat_id, from_chat_id, message_ids, disable_notification, message_thread_id, protect_content, remove_caption) return [types.MessageID.de_json(message_id) for message_id in result] - + async def send_checklist( self, business_connection_id: str, chat_id: Union[int, str], checklist: types.InputChecklist, @@ -3663,7 +3663,7 @@ async def send_checklist( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply @@ -3672,7 +3672,7 @@ async def send_checklist( self.token, business_connection_id, chat_id, checklist, disable_notification=disable_notification, protect_content=protect_content, message_effect_id=message_effect_id, reply_parameters=reply_parameters, reply_markup=reply_markup)) - + async def edit_message_checklist( self, business_connection_id: str, chat_id: Union[int, str], message_id: int, checklist: types.InputChecklist, @@ -3707,9 +3707,9 @@ async def edit_message_checklist( async def send_dice( self, chat_id: Union[int, str], - emoji: Optional[str]=None, disable_notification: Optional[bool]=None, + emoji: Optional[str]=None, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -3752,7 +3752,7 @@ async def send_dice( :param message_thread_id: The identifier of a message thread, unique within the chat to which the message with the thread identifier belongs :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -3771,11 +3771,11 @@ async def send_dice( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -3798,15 +3798,15 @@ async def send_dice( self.token, chat_id, emoji, disable_notification, reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) - + async def send_photo( - self, chat_id: Union[int, str], photo: Union[Any, str], + self, chat_id: Union[int, str], photo: Union[Any, str], caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, @@ -3821,7 +3821,7 @@ async def send_photo( Use this method to send photos. On success, the sent Message is returned. Telegram documentation: https://core.telegram.org/bots/api#sendphoto - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -3864,7 +3864,7 @@ async def send_photo( :param has_spoiler: Pass True, if the photo should be sent as a spoiler :type has_spoiler: :obj:`bool` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -3880,18 +3880,18 @@ async def send_photo( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` - + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -3917,14 +3917,14 @@ async def send_photo( show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) async def send_audio( - self, chat_id: Union[int, str], audio: Union[Any, str], - caption: Optional[str]=None, duration: Optional[int]=None, + self, chat_id: Union[int, str], audio: Union[Any, str], + caption: Optional[str]=None, duration: Optional[int]=None, performer: Optional[str]=None, title: Optional[str]=None, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, @@ -3943,7 +3943,7 @@ async def send_audio( For sending voice messages, use the send_voice method instead. Telegram documentation: https://core.telegram.org/bots/api#sendaudio - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -4000,7 +4000,7 @@ async def send_audio( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4020,7 +4020,7 @@ async def send_audio( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if thumb is not None and thumbnail is None: thumbnail = thumb @@ -4028,7 +4028,7 @@ async def send_audio( if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4053,12 +4053,12 @@ async def send_audio( caption_entities, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_voice( - self, chat_id: Union[int, str], voice: Union[Any, str], - caption: Optional[str]=None, duration: Optional[int]=None, - reply_to_message_id: Optional[int]=None, + self, chat_id: Union[int, str], voice: Union[Any, str], + caption: Optional[str]=None, duration: Optional[int]=None, + reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, - disable_notification: Optional[bool]=None, + parse_mode: Optional[str]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, @@ -4072,7 +4072,7 @@ async def send_voice( Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. Telegram documentation: https://core.telegram.org/bots/api#sendvoice - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -4114,7 +4114,7 @@ async def send_voice( :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4133,11 +4133,11 @@ async def send_voice( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4164,12 +4164,12 @@ async def send_voice( async def send_document( self, chat_id: Union[int, str], document: Union[Any, str], - reply_to_message_id: Optional[int]=None, - caption: Optional[str]=None, + reply_to_message_id: Optional[int]=None, + caption: Optional[str]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, - disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + parse_mode: Optional[str]=None, + disable_notification: Optional[bool]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, @@ -4187,7 +4187,7 @@ async def send_document( Use this method to send general files. Telegram documentation: https://core.telegram.org/bots/api#senddocument - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -4241,7 +4241,7 @@ async def send_document( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4261,7 +4261,7 @@ async def send_document( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if data and not(document): # function typo miss compatibility @@ -4274,7 +4274,7 @@ async def send_document( if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4295,7 +4295,7 @@ async def send_document( if isinstance(document, types.InputFile) and visible_file_name: # inputfile name ignored, warn logger.warning('Cannot use both InputFile and visible_file_name. InputFile name will be ignored.') - + return types.Message.de_json( await asyncio_helper.send_data( self.token, chat_id, document, 'document', @@ -4306,10 +4306,10 @@ async def send_document( message_thread_id = message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_sticker( - self, chat_id: Union[int, str], sticker: Union[Any, str], - reply_to_message_id: Optional[int]=None, + self, chat_id: Union[int, str], sticker: Union[Any, str], + reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -4361,7 +4361,7 @@ async def send_sticker( :param emoji: Emoji associated with the sticker; only for just uploaded stickers :type emoji: :obj:`str` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4380,7 +4380,7 @@ async def send_sticker( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if data and not(sticker): # function typo miss compatibility @@ -4389,7 +4389,7 @@ async def send_sticker( if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4411,23 +4411,23 @@ async def send_sticker( await asyncio_helper.send_data( self.token, chat_id, sticker, 'sticker', reply_markup=reply_markup, - disable_notification=disable_notification, timeout=timeout, + disable_notification=disable_notification, timeout=timeout, protect_content=protect_content, message_thread_id=message_thread_id, emoji=emoji, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def send_video( - self, chat_id: Union[int, str], video: Union[Any, str], + self, chat_id: Union[int, str], video: Union[Any, str], duration: Optional[int]=None, width: Optional[int]=None, height: Optional[int]=None, - thumbnail: Optional[Union[Any, str]]=None, - caption: Optional[str]=None, - parse_mode: Optional[str]=None, + thumbnail: Optional[Union[Any, str]]=None, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - supports_streaming: Optional[bool]=None, + supports_streaming: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, @@ -4444,7 +4444,7 @@ async def send_video( start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). - + Telegram documentation: https://core.telegram.org/bots/api#sendvideo :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -4472,7 +4472,7 @@ async def send_video( :param start_timestamp: Start timestamp for the video in the message :type start_timestamp: :obj:`int` - + :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -4516,7 +4516,7 @@ async def send_video( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4539,11 +4539,11 @@ async def send_video( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4578,19 +4578,19 @@ async def send_video( show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast, cover=cover, start_timestamp=start_timestamp)) async def send_animation( - self, chat_id: Union[int, str], animation: Union[Any, str], + self, chat_id: Union[int, str], animation: Union[Any, str], duration: Optional[int]=None, width: Optional[int]=None, height: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, - caption: Optional[str]=None, + caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, @@ -4603,7 +4603,7 @@ async def send_animation( """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. - + Telegram documentation: https://core.telegram.org/bots/api#sendanimation :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -4621,7 +4621,7 @@ async def send_animation( :param height: Animation height :type height: :obj:`int` - + :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, @@ -4665,7 +4665,7 @@ async def send_animation( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4688,11 +4688,11 @@ async def send_animation( parse_mode = self.parse_mode if (parse_mode is None) else parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4722,13 +4722,13 @@ async def send_animation( message_effect_id=message_effect_id, show_caption_above_media=show_caption_above_media, allow_paid_broadcast=allow_paid_broadcast)) async def send_video_note( - self, chat_id: Union[int, str], data: Union[Any, str], - duration: Optional[int]=None, + self, chat_id: Union[int, str], data: Union[Any, str], + duration: Optional[int]=None, length: Optional[int]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + disable_notification: Optional[bool]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -4743,10 +4743,10 @@ async def send_video_note( Use this method to send video messages. On success, the sent Message is returned. Telegram documentation: https://core.telegram.org/bots/api#sendvideonote - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - + :param data: Video note to send. Pass a file_id as String to send a video note that exists on the Telegram servers (recommended) or upload a new video using multipart/form-data. Sending video notes by a URL is currently unsupported :type data: :obj:`str` or :class:`telebot.types.InputFile` @@ -4774,7 +4774,7 @@ async def send_video_note( :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, - so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . + so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found @@ -4788,7 +4788,7 @@ async def send_video_note( :param thumb: Deprecated. Use thumbnail instead :type thumb: :obj:`str` or :class:`telebot.types.InputFile` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4807,11 +4807,11 @@ async def send_video_note( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -4906,13 +4906,13 @@ async def send_paid_media( payload=payload, allow_paid_broadcast=allow_paid_broadcast)) async def send_media_group( - self, chat_id: Union[int, str], + self, chat_id: Union[int, str], media: List[Union[ - types.InputMediaAudio, types.InputMediaDocument, + types.InputMediaAudio, types.InputMediaDocument, types.InputMediaPhoto, types.InputMediaVideo]], - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, + reply_to_message_id: Optional[int]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, message_thread_id: Optional[int]=None, @@ -4923,7 +4923,7 @@ async def send_media_group( """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. - + Telegram documentation: https://core.telegram.org/bots/api#sendmediagroup :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -4949,7 +4949,7 @@ async def send_media_group( :param message_thread_id: Identifier of a message thread, in which the messages will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -4973,11 +4973,11 @@ async def send_media_group( media_item.parse_mode = self.parse_mode disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -5001,16 +5001,16 @@ async def send_media_group( return [types.Message.de_json(msg) for msg in result] async def send_location( - self, chat_id: Union[int, str], - latitude: float, longitude: float, - live_period: Optional[int]=None, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, + self, chat_id: Union[int, str], + latitude: float, longitude: float, + live_period: Optional[int]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, - horizontal_accuracy: Optional[float]=None, - heading: Optional[int]=None, - proximity_alert_radius: Optional[int]=None, + horizontal_accuracy: Optional[float]=None, + heading: Optional[int]=None, + proximity_alert_radius: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, @@ -5060,13 +5060,13 @@ async def send_location( :param allow_sending_without_reply: Deprecated - Use reply_parameters instead. Pass True, if the message should be sent even if the specified replied-to message is not found :type allow_sending_without_reply: :obj:`bool` - + :param protect_content: Protects the contents of the sent message from forwarding and saving :type protect_content: :obj:`bool` :param message_thread_id: Identifier of a message thread, in which the message will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -5085,11 +5085,11 @@ async def send_location( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -5109,20 +5109,20 @@ async def send_location( return types.Message.de_json( await asyncio_helper.send_location( - self.token, chat_id, latitude, longitude, live_period, - reply_markup, disable_notification, timeout, - horizontal_accuracy, heading, proximity_alert_radius, + self.token, chat_id, latitude, longitude, live_period, + reply_markup, disable_notification, timeout, + horizontal_accuracy, heading, proximity_alert_radius, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def edit_message_live_location( - self, latitude: float, longitude: float, - chat_id: Optional[Union[int, str]]=None, + self, latitude: float, longitude: float, + chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, - horizontal_accuracy: Optional[float]=None, - heading: Optional[int]=None, + horizontal_accuracy: Optional[float]=None, + heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, live_period: Optional[int]=None, business_connection_id: Optional[str]=None @@ -5182,9 +5182,9 @@ async def edit_message_live_location( ) async def stop_message_live_location( - self, chat_id: Optional[Union[int, str]]=None, + self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, business_connection_id: Optional[str]=None) -> types.Message: @@ -5193,7 +5193,7 @@ async def stop_message_live_location( On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. Telegram documentation: https://core.telegram.org/bots/api#stopmessagelivelocation - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -5221,14 +5221,14 @@ async def stop_message_live_location( self.token, chat_id, message_id, inline_message_id, reply_markup, timeout, business_connection_id)) async def send_venue( - self, chat_id: Union[int, str], - latitude: float, longitude: float, - title: str, address: str, - foursquare_id: Optional[str]=None, + self, chat_id: Union[int, str], + latitude: float, longitude: float, + title: str, address: str, + foursquare_id: Optional[str]=None, foursquare_type: Optional[str]=None, - disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, google_place_id: Optional[str]=None, @@ -5241,12 +5241,12 @@ async def send_venue( allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. - + Telegram documentation: https://core.telegram.org/bots/api#sendvenue :param chat_id: Unique identifier for the target chat or username of the target channel :type chat_id: :obj:`int` or :obj:`str` - + :param latitude: Latitude of the venue :type latitude: :obj:`float` @@ -5295,7 +5295,7 @@ async def send_venue( :param message_thread_id: The thread to which the message will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -5304,7 +5304,7 @@ async def send_venue( :param message_effect_id: Unique identifier of the message effect :type message_effect_id: :obj:`str` - + :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` @@ -5314,11 +5314,11 @@ async def send_venue( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -5342,15 +5342,15 @@ async def send_venue( disable_notification, reply_markup, timeout, google_place_id, google_place_type, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) - + async def send_contact( - self, chat_id: Union[int, str], phone_number: str, - first_name: str, last_name: Optional[str]=None, + self, chat_id: Union[int, str], phone_number: str, + first_name: str, last_name: Optional[str]=None, vcard: Optional[str]=None, - disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -5402,7 +5402,7 @@ async def send_contact( :param message_thread_id: The thread to which the message will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -5421,11 +5421,11 @@ async def send_contact( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -5448,7 +5448,7 @@ async def send_contact( self.token, chat_id, phone_number, first_name, last_name, vcard, disable_notification, reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) - + async def send_chat_action( self, chat_id: Union[int, str], action: str, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, @@ -5465,7 +5465,7 @@ async def send_chat_action( :param chat_id: Unique identifier for the target chat or username of the target channel :type chat_id: :obj:`int` or :obj:`str` - + :param action: Type of action to broadcast. Choose one, depending on what the user is about to receive: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_voice or upload_voice for voice notes, upload_document for general files, @@ -5487,8 +5487,8 @@ async def send_chat_action( return await asyncio_helper.send_chat_action(self.token, chat_id, action, timeout, message_thread_id, business_connection_id) async def kick_chat_member( - self, chat_id: Union[int, str], user_id: int, - until_date:Optional[Union[int, datetime]]=None, + self, chat_id: Union[int, str], user_id: int, + until_date:Optional[Union[int, datetime]]=None, revoke_messages: Optional[bool]=None) -> bool: """ This function is deprecated. Use `ban_chat_member` instead @@ -5497,13 +5497,13 @@ async def kick_chat_member( return await asyncio_helper.ban_chat_member(self.token, chat_id, user_id, until_date, revoke_messages) async def ban_chat_member( - self, chat_id: Union[int, str], user_id: int, - until_date:Optional[Union[int, datetime]]=None, + self, chat_id: Union[int, str], user_id: int, + until_date:Optional[Union[int, datetime]]=None, revoke_messages: Optional[bool]=None) -> bool: """ - Use this method to ban a user in a group, a supergroup or a channel. - In the case of supergroups and channels, the user will not be able to return to the chat on their - own using invite links, etc., unless unbanned first. + Use this method to ban a user in a group, a supergroup or a channel. + In the case of supergroups and channels, the user will not be able to return to the chat on their + own using invite links, etc., unless unbanned first. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#banchatmember @@ -5520,17 +5520,17 @@ async def ban_chat_member( :type until_date: :obj:`int` or :obj:`datetime` :param revoke_messages: Bool: Pass True to delete all messages from the chat for the user that is being removed. - If False, the user will be able to see messages in the group that were sent before the user was removed. + If False, the user will be able to see messages in the group that were sent before the user was removed. Always True for supergroups and channels. :type revoke_messages: :obj:`bool` - + :return: Returns True on success. :rtype: :obj:`bool` """ return await asyncio_helper.ban_chat_member(self.token, chat_id, user_id, until_date, revoke_messages) async def unban_chat_member( - self, chat_id: Union[int, str], user_id: int, + self, chat_id: Union[int, str], user_id: int, only_if_banned: Optional[bool]=False) -> bool: """ Use this method to unban a previously kicked user in a supergroup or channel. @@ -5557,15 +5557,15 @@ async def unban_chat_member( return await asyncio_helper.unban_chat_member(self.token, chat_id, user_id, only_if_banned) async def restrict_chat_member( - self, chat_id: Union[int, str], user_id: int, + self, chat_id: Union[int, str], user_id: int, until_date: Optional[Union[int, datetime]]=None, - can_send_messages: Optional[bool]=None, + can_send_messages: Optional[bool]=None, can_send_media_messages: Optional[bool]=None, - can_send_polls: Optional[bool]=None, + can_send_polls: Optional[bool]=None, can_send_other_messages: Optional[bool]=None, - can_add_web_page_previews: Optional[bool]=None, + can_add_web_page_previews: Optional[bool]=None, can_change_info: Optional[bool]=None, - can_invite_users: Optional[bool]=None, + can_invite_users: Optional[bool]=None, can_pin_messages: Optional[bool]=None, permissions: Optional[types.ChatPermissions]=None, use_independent_chat_permissions: Optional[bool]=None) -> bool: @@ -5593,10 +5593,10 @@ async def restrict_chat_member( :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` - + :param can_send_media_messages: deprecated :type can_send_media_messages: :obj:`bool` - + :param can_send_polls: deprecated :type can_send_polls: :obj:`bool` @@ -5644,17 +5644,17 @@ async def restrict_chat_member( self.token, chat_id, user_id, permissions, until_date, use_independent_chat_permissions) async def promote_chat_member( - self, chat_id: Union[int, str], user_id: int, - can_change_info: Optional[bool]=None, + self, chat_id: Union[int, str], user_id: int, + can_change_info: Optional[bool]=None, can_post_messages: Optional[bool]=None, - can_edit_messages: Optional[bool]=None, - can_delete_messages: Optional[bool]=None, + can_edit_messages: Optional[bool]=None, + can_delete_messages: Optional[bool]=None, can_invite_users: Optional[bool]=None, - can_restrict_members: Optional[bool]=None, - can_pin_messages: Optional[bool]=None, + can_restrict_members: Optional[bool]=None, + can_pin_messages: Optional[bool]=None, can_promote_members: Optional[bool]=None, - is_anonymous: Optional[bool]=None, - can_manage_chat: Optional[bool]=None, + is_anonymous: Optional[bool]=None, + can_manage_chat: Optional[bool]=None, can_manage_video_chats: Optional[bool]=None, can_manage_voice_chats: Optional[bool]=None, can_manage_topics: Optional[bool]=None, @@ -5704,9 +5704,9 @@ async def promote_chat_member( :param is_anonymous: Pass True, if the administrator's presence in the chat is hidden :type is_anonymous: :obj:`bool` - :param can_manage_chat: Pass True, if the administrator can access the chat event log, chat statistics, - message statistics in channels, see channel members, - see anonymous administrators in supergroups and ignore slow mode. + :param can_manage_chat: Pass True, if the administrator can access the chat event log, chat statistics, + message statistics in channels, see channel members, + see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege :type can_manage_chat: :obj:`bool` @@ -5774,10 +5774,10 @@ async def set_chat_administrator_custom_title( async def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ Use this method to ban a channel chat in a supergroup or a channel. - The owner of the chat will not be able to send messages and join live - streams on behalf of the chat, unless it is unbanned first. - The bot must be an administrator in the supergroup or channel - for this to work and must have the appropriate administrator rights. + The owner of the chat will not be able to send messages and join live + streams on behalf of the chat, unless it is unbanned first. + The bot must be an administrator in the supergroup or channel + for this to work and must have the appropriate administrator rights. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#banchatsenderchat @@ -5795,8 +5795,8 @@ async def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: U async def unban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ - Use this method to unban a previously banned channel chat in a supergroup or channel. - The bot must be an administrator for this to work and must have the appropriate + Use this method to unban a previously banned channel chat in a supergroup or channel. + The bot must be an administrator for this to work and must have the appropriate administrator rights. Returns True on success. @@ -5844,7 +5844,7 @@ async def set_chat_permissions( async def create_chat_invite_link( self, chat_id: Union[int, str], name: Optional[str]=None, - expire_date: Optional[Union[int, datetime]]=None, + expire_date: Optional[Union[int, datetime]]=None, member_limit: Optional[int]=None, creates_join_request: Optional[bool]=None) -> types.ChatInviteLink: """ @@ -5916,7 +5916,7 @@ async def edit_chat_invite_link( return types.ChatInviteLink.de_json( await asyncio_helper.edit_chat_invite_link(self.token, chat_id, invite_link, name, expire_date, member_limit, creates_join_request) ) - + async def create_chat_subscription_invite_link( self, chat_id: Union[int, str], subscription_period: int, subscription_price: int, name: Optional[str]=None) -> types.ChatInviteLink: @@ -5930,7 +5930,7 @@ async def create_chat_subscription_invite_link( :param chat_id: Unique identifier for the target channel chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - + :param name: Invite link name; 0-32 characters :type name: :obj:`str` @@ -5978,7 +5978,7 @@ async def revoke_chat_invite_link( self, chat_id: Union[int, str], invite_link: str) -> types.ChatInviteLink: """ Use this method to revoke an invite link created by the bot. - Note: If the primary link is revoked, a new link is automatically generated The bot must be an administrator + Note: If the primary link is revoked, a new link is automatically generated The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Telegram documentation: https://core.telegram.org/bots/api#revokechatinvitelink @@ -6016,7 +6016,7 @@ async def export_chat_invite_link(self, chat_id: Union[int, str]) -> str: async def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ - Use this method to approve a chat join request. + Use this method to approve a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns True on success. @@ -6036,7 +6036,7 @@ async def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Uni async def decline_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ - Use this method to decline a chat join request. + Use this method to decline a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns True on success. @@ -6092,7 +6092,7 @@ async def delete_chat_photo(self, chat_id: Union[int, str]) -> bool: :rtype: :obj:`bool` """ return await asyncio_helper.delete_chat_photo(self.token, chat_id) - + async def set_my_description(self, description: Optional[str]=None, language_code: Optional[str]=None): """ Use this method to change the bot's description, which is shown in @@ -6123,11 +6123,11 @@ async def get_my_description(self, language_code: Optional[str]=None): """ result = await asyncio_helper.get_my_description(self.token, language_code) return types.BotDescription.de_json(result) - + async def set_my_short_description(self, short_description:Optional[str]=None, language_code:Optional[str]=None): """ Use this method to change the bot's short description, which is shown on the bot's profile page and - is sent together with the link when users share the bot. + is sent together with the link when users share the bot. Returns True on success. :param short_description: New short description for the bot; 0-120 characters. Pass an empty string to remove the dedicated short description for the given language. @@ -6141,7 +6141,7 @@ async def set_my_short_description(self, short_description:Optional[str]=None, l """ return await asyncio_helper.set_my_short_description(self.token, short_description, language_code) - + async def get_my_short_description(self, language_code: Optional[str]=None): """ Use this method to get the current bot short description for the given user language. @@ -6154,21 +6154,21 @@ async def get_my_short_description(self, language_code: Optional[str]=None): """ result = await asyncio_helper.get_my_short_description(self.token, language_code) return types.BotShortDescription.de_json(result) - - async def get_my_commands(self, scope: Optional[types.BotCommandScope], + + async def get_my_commands(self, scope: Optional[types.BotCommandScope], language_code: Optional[str]) -> List[types.BotCommand]: """ - Use this method to get the current list of the bot's commands. + Use this method to get the current list of the bot's commands. Returns List of BotCommand on success. Telegram documentation: https://core.telegram.org/bots/api#getmycommands - :param scope: The scope of users for which the commands are relevant. + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -6212,16 +6212,16 @@ async def get_my_name(self, language_code: Optional[str]=None): result = await asyncio_helper.get_my_name(self.token, language_code) return types.BotName.de_json(result) - async def set_chat_menu_button(self, chat_id: Union[int, str]=None, + async def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ - Use this method to change the bot's menu button in a private chat, - or the default menu button. + Use this method to change the bot's menu button in a private chat, + or the default menu button. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setchatmenubutton - :param chat_id: Unique identifier for the target private chat. + :param chat_id: Unique identifier for the target private chat. If not specified, default bot's menu button will be changed. :type chat_id: :obj:`int` or :obj:`str` @@ -6252,13 +6252,13 @@ async def get_chat_menu_button(self, chat_id: Union[int, str]=None) -> types.Men return types.MenuButton.de_json(await asyncio_helper.get_chat_menu_button(self.token, chat_id)) - async def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, + async def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, for_channels: bool=None) -> bool: """ Use this method to change the default administrator rights requested by the bot when it's added as an administrator to groups or channels. These rights will be suggested to users, but they are are free to modify - the list before adding the bot. + the list before adding the bot. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmydefaultadministratorrights @@ -6276,7 +6276,7 @@ async def set_my_default_administrator_rights(self, rights: types.ChatAdministra """ return await asyncio_helper.set_my_default_administrator_rights(self.token, rights, for_channels) - + async def get_my_default_administrator_rights(self, for_channels: bool=None) -> types.ChatAdministratorRights: """ @@ -6291,9 +6291,9 @@ async def get_my_default_administrator_rights(self, for_channels: bool=None) -> :return: Returns ChatAdministratorRights on success. :rtype: :class:`telebot.types.ChatAdministratorRights` """ - + return types.ChatAdministratorRights.de_json(await asyncio_helper.get_my_default_administrator_rights(self.token, for_channels)) - + async def get_business_connection(self, business_connection_id: str) -> types.BusinessConnection: """ Use this method to get information about the connection of the bot with a business account. @@ -6312,9 +6312,9 @@ async def get_business_connection(self, business_connection_id: str) -> types.Bu return types.BusinessConnection.de_json( result ) - - async def set_my_commands(self, commands: List[types.BotCommand], + + async def set_my_commands(self, commands: List[types.BotCommand], scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> bool: """ @@ -6325,12 +6325,12 @@ async def set_my_commands(self, commands: List[types.BotCommand], :param commands: List of BotCommand. At most 100 commands can be specified. :type commands: :obj:`list` of :class:`telebot.types.BotCommand` - :param scope: The scope of users for which the commands are relevant. + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -6338,22 +6338,22 @@ async def set_my_commands(self, commands: List[types.BotCommand], :rtype: :obj:`bool` """ return await asyncio_helper.set_my_commands(self.token, commands, scope, language_code) - - async def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, + + async def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[int]=None) -> bool: """ - Use this method to delete the list of the bot's commands for the given scope and user language. - After deletion, higher level commands will be shown to affected users. + Use this method to delete the list of the bot's commands for the given scope and user language. + After deletion, higher level commands will be shown to affected users. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#deletemycommands - - :param scope: The scope of users for which the commands are relevant. + + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -6404,7 +6404,7 @@ async def set_chat_description(self, chat_id: Union[int, str], description: Opti return await asyncio_helper.set_chat_description(self.token, chat_id, description) async def pin_chat_message( - self, chat_id: Union[int, str], message_id: int, + self, chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=False, business_connection_id: Optional[str]=None) -> bool: """ Use this method to pin a message in a supergroup. @@ -6475,10 +6475,10 @@ async def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: return await asyncio_helper.unpin_all_chat_messages(self.token, chat_id) async def edit_message_text( - self, text: str, - chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + self, text: str, + chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, + inline_message_id: Optional[str]=None, parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, @@ -6556,9 +6556,9 @@ async def edit_message_text( return types.Message.de_json(result) async def edit_message_media( - self, media: Any, chat_id: Optional[Union[int, str]]=None, + self, media: Any, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: @@ -6567,7 +6567,7 @@ async def edit_message_media( If a message is part of a message album, then it can be edited only to an audio for audio albums, only to a document for document albums and to a photo or a video otherwise. When an inline message is edited, a new file can't be uploaded; use a previously uploaded file via its file_id or specify a URL. On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. - Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. + Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. Telegram documentation: https://core.telegram.org/bots/api#editmessagemedia @@ -6576,7 +6576,7 @@ async def edit_message_media( :param chat_id: Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - :param message_id: Required if inline_message_id is not specified. Identifier of the sent message + :param message_id: Required if inline_message_id is not specified. Identifier of the sent message :type message_id: :obj:`int` :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message @@ -6601,9 +6601,9 @@ async def edit_message_media( return types.Message.de_json(result) async def edit_message_reply_markup( - self, chat_id: Optional[Union[int, str]]=None, + self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: @@ -6640,10 +6640,10 @@ async def edit_message_reply_markup( return types.Message.de_json(result) async def send_game( - self, chat_id: Union[int, str], game_short_name: str, + self, chat_id: Union[int, str], game_short_name: str, disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -6666,7 +6666,7 @@ async def send_game( :param disable_notification: Sends the message silently. Users will receive a notification with no sound. :type disable_notification: :obj:`bool` - :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message + :param reply_to_message_id: Deprecated - Use reply_parameters instead. If the message is a reply, ID of the original message :type reply_to_message_id: :obj:`int` :param reply_markup: Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -6683,7 +6683,7 @@ async def send_game( :param message_thread_id: Identifier of the thread to which the message will be sent. :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -6702,11 +6702,11 @@ async def send_game( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -6726,15 +6726,15 @@ async def send_game( result = await asyncio_helper.send_game( self.token, chat_id, game_short_name, disable_notification, - reply_markup, timeout, + reply_markup, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) return types.Message.de_json(result) async def set_game_score( - self, user_id: Union[int, str], score: int, - force: Optional[bool]=None, - chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + self, user_id: Union[int, str], score: int, + force: Optional[bool]=None, + chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None, disable_edit_message: Optional[bool]=None) -> Union[types.Message, bool]: """ @@ -6774,7 +6774,7 @@ async def set_game_score( async def get_game_high_scores( self, user_id: int, chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None) -> List[types.GameHighScore]: """ Use this method to get data for high score tables. Will return the score of the specified user and several of @@ -6805,20 +6805,20 @@ async def get_game_high_scores( return [types.GameHighScore.de_json(r) for r in result] async def send_invoice( - self, chat_id: Union[int, str], title: str, description: str, - invoice_payload: str, provider_token: Union[str, None], currency: str, - prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, - photo_url: Optional[str]=None, photo_size: Optional[int]=None, + self, chat_id: Union[int, str], title: str, description: str, + invoice_payload: str, provider_token: Union[str, None], currency: str, + prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, + photo_url: Optional[str]=None, photo_size: Optional[int]=None, photo_width: Optional[int]=None, photo_height: Optional[int]=None, - need_name: Optional[bool]=None, need_phone_number: Optional[bool]=None, + need_name: Optional[bool]=None, need_phone_number: Optional[bool]=None, need_email: Optional[bool]=None, need_shipping_address: Optional[bool]=None, - send_phone_number_to_provider: Optional[bool]=None, - send_email_to_provider: Optional[bool]=None, + send_phone_number_to_provider: Optional[bool]=None, + send_email_to_provider: Optional[bool]=None, is_flexible: Optional[bool]=None, - disable_notification: Optional[bool]=None, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - provider_data: Optional[str]=None, + disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + provider_data: Optional[str]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, max_tip_amount: Optional[int] = None, @@ -6869,7 +6869,7 @@ async def send_invoice( :param photo_size: Photo size in bytes :type photo_size: :obj:`int` - :param photo_width: Photo width + :param photo_width: Photo width :type photo_width: :obj:`int` :param photo_height: Photo height @@ -6929,7 +6929,7 @@ async def send_invoice( :param message_thread_id: The identifier of a message thread, in which the invoice message will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -6945,11 +6945,11 @@ async def send_invoice( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -6979,9 +6979,9 @@ async def send_invoice( async def create_invoice_link(self, - title: str, description: str, payload:str, provider_token: Union[str, None], + title: str, description: str, payload:str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], - max_tip_amount: Optional[int] = None, + max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, provider_data: Optional[str]=None, photo_url: Optional[str]=None, @@ -6997,14 +6997,14 @@ async def create_invoice_link(self, is_flexible: Optional[bool]=None, subscription_period: Optional[int]=None, business_connection_id: Optional[str]=None) -> str: - + """ - Use this method to create a link for an invoice. + Use this method to create a link for an invoice. Returns the created invoice link as String on success. Telegram documentation: https://core.telegram.org/bots/api#createinvoicelink - + :param business_connection_id: Unique identifier of the business connection on behalf of which the link will be created :type business_connection_id: :obj:`str` @@ -7095,18 +7095,18 @@ async def create_invoice_link(self, # noinspection PyShadowingBuiltins async def send_poll( self, chat_id: Union[int, str], question: str, options: List[Union[str, types.InputPollOption]], - is_anonymous: Optional[bool]=None, type: Optional[str]=None, - allows_multiple_answers: Optional[bool]=None, + is_anonymous: Optional[bool]=None, type: Optional[str]=None, + allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, - explanation: Optional[str]=None, - explanation_parse_mode: Optional[str]=None, - open_period: Optional[int]=None, - close_date: Optional[Union[int, datetime]]=None, + explanation: Optional[str]=None, + explanation_parse_mode: Optional[str]=None, + open_period: Optional[int]=None, + close_date: Optional[Union[int, datetime]]=None, is_closed: Optional[bool]=None, disable_notification: Optional[bool]=False, - reply_to_message_id: Optional[int]=None, - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - allow_sending_without_reply: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + allow_sending_without_reply: Optional[bool]=None, timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, protect_content: Optional[bool]=None, @@ -7186,7 +7186,7 @@ async def send_poll( :param message_thread_id: The identifier of a message thread, in which the poll will be sent :type message_thread_id: :obj:`int` - + :param reply_parameters: Reply parameters. :type reply_parameters: :class:`telebot.types.ReplyParameters` @@ -7211,13 +7211,13 @@ async def send_poll( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + explanation_parse_mode = self.parse_mode if (explanation_parse_mode is None) else explanation_parse_mode question_parse_mode = self.parse_mode if (question_parse_mode is None) else question_parse_mode if allow_sending_without_reply is not None: logger.warning("The parameter 'allow_sending_without_reply' is deprecated. Use 'reply_parameters' instead.") - + if reply_to_message_id: # show a deprecation warning logger.warning("The parameter 'reply_to_message_id' is deprecated. Use 'reply_parameters' instead.") @@ -7261,7 +7261,7 @@ async def send_poll( message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast)) async def stop_poll( - self, chat_id: Union[int, str], message_id: int, + self, chat_id: Union[int, str], message_id: int, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None) -> types.Poll: """ @@ -7287,8 +7287,8 @@ async def stop_poll( return types.Poll.de_json(await asyncio_helper.stop_poll(self.token, chat_id, message_id, reply_markup, business_connection_id)) async def answer_shipping_query( - self, shipping_query_id: str, ok: bool, - shipping_options: Optional[List[types.ShippingOption]]=None, + self, shipping_query_id: str, ok: bool, + shipping_options: Optional[List[types.ShippingOption]]=None, error_message: Optional[str]=None) -> bool: """ Asks for an answer to a shipping question. @@ -7314,7 +7314,7 @@ async def answer_shipping_query( return await asyncio_helper.answer_shipping_query(self.token, shipping_query_id, ok, shipping_options, error_message) async def answer_pre_checkout_query( - self, pre_checkout_query_id: str, ok: bool, + self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str]=None) -> bool: """ Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the @@ -7326,7 +7326,7 @@ async def answer_pre_checkout_query( Telegram documentation: https://core.telegram.org/bots/api#answerprecheckoutquery - :param pre_checkout_query_id: Unique identifier for the query to be answered + :param pre_checkout_query_id: Unique identifier for the query to be answered :type pre_checkout_query_id: :obj:`int` :param ok: Specify True if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. Use False if there are any problems. @@ -7349,7 +7349,7 @@ async def get_my_star_balance(self) -> types.StarAmount: On success, returns a StarAmount object. """ return types.StarAmount.de_json(await asyncio_helper.get_my_star_balance(self.token)) - + async def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int]=None) -> types.StarTransactions: """ Returns the bot's Telegram Star transactions in chronological order. @@ -7367,7 +7367,7 @@ async def get_star_transactions(self, offset: Optional[int]=None, limit: Optiona """ return types.StarTransactions.de_json(await asyncio_helper.get_star_transactions(self.token, offset, limit)) - + async def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: """ Refunds a successful payment in Telegram Stars. Returns True on success. @@ -7406,10 +7406,10 @@ async def edit_user_star_subscription(self, user_id: int, telegram_payment_charg return await asyncio_helper.edit_user_star_subscription(self.token, user_id, telegram_payment_charge_id, is_canceled) async def edit_message_caption( - self, caption: str, chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + self, caption: str, chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - parse_mode: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, show_caption_above_media: Optional[bool]=None, @@ -7466,7 +7466,7 @@ async def edit_message_caption( async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message: """ Convenience function for `send_message(message.chat.id, text, reply_parameters=(message.message_id...), **kwargs)` - + :param message: Instance of :class:`telebot.types.Message` :type message: :obj:`types.Message` @@ -7497,12 +7497,12 @@ async def reply_to(self, message: types.Message, text: str, **kwargs) -> types.M return await self.send_message(message.chat.id, text, reply_parameters=reply_parameters, **kwargs) async def answer_inline_query( - self, inline_query_id: str, - results: List[Any], - cache_time: Optional[int]=None, - is_personal: Optional[bool]=None, + self, inline_query_id: str, + results: List[Any], + cache_time: Optional[int]=None, + is_personal: Optional[bool]=None, next_offset: Optional[str]=None, - switch_pm_text: Optional[str]=None, + switch_pm_text: Optional[str]=None, switch_pm_parameter: Optional[str]=None, button: Optional[types.InlineQueryResultsButton]=None) -> bool: """ @@ -7555,7 +7555,7 @@ async def answer_inline_query( async def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bool: """ - Use this method to clear the list of pinned messages in a General forum topic. + Use this method to clear the list of pinned messages in a General forum topic. The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator right in the supergroup. Returns True on success. @@ -7572,8 +7572,8 @@ async def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) return await asyncio_helper.unpin_all_general_forum_topic_messages(self.token, chat_id) async def answer_callback_query( - self, callback_query_id: int, - text: Optional[str]=None, show_alert: Optional[bool]=None, + self, callback_query_id: int, + text: Optional[str]=None, show_alert: Optional[bool]=None, url: Optional[str]=None, cache_time: Optional[int]=None) -> bool: """ Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to @@ -7601,14 +7601,14 @@ async def answer_callback_query( :rtype: :obj:`bool` """ return await asyncio_helper.answer_callback_query(self.token, callback_query_id, text, show_alert, url, cache_time) - + # getUserChatBoosts # Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. # Parameter Type Required Description # chat_id Integer or String Yes Unique identifier for the chat or username of the channel (in the format @channelusername) # user_id Integer Yes Unique identifier of the target user - + async def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts: """ Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. @@ -7627,11 +7627,11 @@ async def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> result = await asyncio_helper.get_user_chat_boosts(self.token, chat_id, user_id) return types.UserChatBoosts.de_json(result) - + async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None, format: Optional[str]=None) -> bool: """ - Use this method to set the thumbnail of a sticker set. + Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumbnail @@ -7657,11 +7657,11 @@ async def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Un logger.warning("Deprecation warning. 'format' parameter is required in set_sticker_set_thumbnail. Setting format to 'static'.") format = "static" return await asyncio_helper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) - + @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") async def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]=None): """ - Use this method to set the thumbnail of a sticker set. + Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumb @@ -7684,7 +7684,7 @@ async def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, async def get_sticker_set(self, name: str) -> types.StickerSet: """ Use this method to get a sticker set. On success, a StickerSet object is returned. - + Telegram documentation: https://core.telegram.org/bots/api#getstickerset :param name: Sticker set name @@ -7695,7 +7695,7 @@ async def get_sticker_set(self, name: str) -> types.StickerSet: """ result = await asyncio_helper.get_sticker_set(self.token, name) return types.StickerSet.de_json(result) - + async def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: """ Use this method to change search keywords assigned to a regular or custom emoji sticker. @@ -7712,7 +7712,7 @@ async def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> :rtype: :obj:`bool` """ return await asyncio_helper.set_sticker_keywords(self.token, sticker, keywords) - + async def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosition=None) -> bool: """ Use this method to change the mask position of a mask sticker. @@ -7748,7 +7748,7 @@ async def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=N """ Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success. - + Telegram documentation: https://core.telegram.org/bots/api#uploadstickerfile :param user_id: User identifier of sticker set owner @@ -7762,7 +7762,7 @@ async def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=N See https://core.telegram.org/stickers for technical requirements. More information on Sending Files » :type sticker: :class:`telebot.types.InputFile` - :param sticker_format: One of "static", "animated", "video". + :param sticker_format: One of "static", "animated", "video". :type sticker_format: :obj:`str` :return: On success, the sent file is returned. @@ -7772,10 +7772,10 @@ async def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=N logger.warning('The parameter "png_sticker" is deprecated. Use "sticker" instead.') sticker = png_sticker sticker_format = "static" - + result = await asyncio_helper.upload_sticker_file(self.token, user_id, sticker, sticker_format) return types.File.de_json(result) - + async def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Optional[str]=None) -> bool: """ Use this method to set the thumbnail of a custom emoji sticker set. @@ -7791,7 +7791,7 @@ async def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_i :rtype: :obj:`bool` """ return await asyncio_helper.set_custom_emoji_sticker_set_thumbnail(self.token, name, custom_emoji_id) - + async def set_sticker_set_title(self, name: str, title: str) -> bool: """ Use this method to set the title of a created sticker set. @@ -7857,13 +7857,13 @@ async def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: st """ if user_id is None and chat_id is None: raise ValueError("Either user_id or chat_id must be specified.") - + if gift_id is None: raise ValueError("gift_id must be specified.") - + return await asyncio_helper.send_gift(self.token, gift_id, text, text_parse_mode, text_entities, pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) - + async def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. @@ -7927,7 +7927,7 @@ async def remove_chat_verification(self, chat_id: int) -> bool: :rtype: :obj:`bool` """ return await asyncio_helper.remove_chat_verification(self.token, chat_id) - + async def read_business_message(self, business_connection_id: str, chat_id: Union[int, str], message_id: int) -> bool: """ Marks incoming message as read on behalf of a business account. Requires the can_read_messages business bot right. Returns True on success. @@ -8019,7 +8019,7 @@ async def set_business_account_bio(self, business_connection_id: str, bio: Optio :rtype: :obj:`bool` """ return await asyncio_helper.set_business_account_bio(self.token, business_connection_id, bio=bio) - + async def set_business_account_gift_settings( self, business_connection_id: str, show_gift_button: bool, accepted_gift_types: types.AcceptedGiftTypes) -> bool: """ @@ -8040,11 +8040,11 @@ async def set_business_account_gift_settings( :rtype: :obj:`bool` """ return await asyncio_helper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) - + async def get_business_account_star_balance(self, business_connection_id: str) -> types.StarAmount: """ Returns the amount of Telegram Stars owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns StarAmount on success. - + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountstarbalance :param business_connection_id: Unique identifier of the business connection @@ -8056,7 +8056,7 @@ async def get_business_account_star_balance(self, business_connection_id: str) - return types.StarAmount.de_json( await asyncio_helper.get_business_account_star_balance(self.token, business_connection_id) ) - + async def transfer_business_account_stars(self, business_connection_id: str, star_count: int) -> bool: """ Transfers Telegram Stars from the business account balance to the bot's balance. Requires the can_transfer_stars business bot right. Returns True on success. @@ -8073,7 +8073,7 @@ async def transfer_business_account_stars(self, business_connection_id: str, sta :rtype: :obj:`bool` """ return await asyncio_helper.transfer_business_account_stars(self.token, business_connection_id, star_count) - + async def get_business_account_gifts( self, business_connection_id: str, exclude_unsaved: Optional[bool]=None, @@ -8086,7 +8086,7 @@ async def get_business_account_gifts( limit: Optional[int]=None) -> types.OwnedGifts: """ Returns the gifts received and owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns OwnedGifts on success. - + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountgifts :param business_connection_id: Unique identifier of the business connection @@ -8132,7 +8132,7 @@ async def get_business_account_gifts( limit=limit ) ) - + async def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id: str) -> bool: """ Converts a given regular gift to Telegram Stars. Requires the can_convert_gifts_to_stars business bot right. Returns True on success. @@ -8149,7 +8149,7 @@ async def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id :rtype: :obj:`bool` """ return await asyncio_helper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) - + async def upgrade_gift( self, business_connection_id: str, owned_gift_id: str, keep_original_details: Optional[bool]=None, @@ -8213,7 +8213,7 @@ async def transfer_gift( new_owner_chat_id, star_count=star_count ) - + async def post_story( self, business_connection_id: str, content: types.InputStoryContent, active_period: int, caption: Optional[str]=None, @@ -8320,7 +8320,7 @@ async def edit_story( async def delete_story(self, business_connection_id: str, story_id: int) -> bool: """ Deletes a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletestory :param business_connection_id: Unique identifier of the business connection @@ -8333,7 +8333,7 @@ async def delete_story(self, business_connection_id: str, story_id: int) -> bool :rtype: :obj:`bool` """ return await asyncio_helper.delete_story(self.token, business_connection_id, story_id) - + async def set_business_account_profile_photo( self, business_connection_id: str, photo: types.InputProfilePhoto, is_public: Optional[bool]=None) -> bool: @@ -8375,7 +8375,7 @@ async def remove_business_account_profile_photo( :rtype: :obj:`bool` """ return await asyncio_helper.remove_business_account_profile_photo(self.token, business_connection_id, is_public=is_public) - + async def gift_premium_subscription( self, user_id: int, month_count: int, star_count: int, text: Optional[str]=None, text_parse_mode: Optional[str]=None, @@ -8424,7 +8424,7 @@ async def get_available_gifts(self) -> types.Gifts: return types.Gifts.de_json(await asyncio_helper.get_available_gifts(self.token)) - + async def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, sticker: types.InputSticker) -> bool: """ Use this method to replace an existing sticker in a sticker set with a new one. The method is equivalent to calling deleteStickerFromSet, then addStickerToSet, @@ -8469,10 +8469,10 @@ async def set_sticker_emoji_list(self, name: str, emoji_list: List[str]) -> bool async def create_new_sticker_set( - self, user_id: int, name: str, title: str, + self, user_id: int, name: str, title: str, emojis: Optional[List[str]]=None, - png_sticker: Union[Any, str]=None, - tgs_sticker: Union[Any, str]=None, + png_sticker: Union[Any, str]=None, + tgs_sticker: Union[Any, str]=None, webm_sticker: Union[Any, str]=None, contains_masks: Optional[bool]=None, sticker_type: Optional[str]=None, @@ -8481,7 +8481,7 @@ async def create_new_sticker_set( stickers: List[types.InputSticker]=None, sticker_format: Optional[str]=None) -> bool: """ - Use this method to create new sticker set owned by a user. + Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success. @@ -8545,7 +8545,7 @@ async def create_new_sticker_set( sticker_format = 'video' elif png_sticker: sticker_format = 'static' - + if contains_masks is not None: logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type" instead') if sticker_type is None: @@ -8556,7 +8556,7 @@ async def create_new_sticker_set( if stickers is None: raise ValueError('You must pass at least one sticker') stickers = [types.InputSticker(sticker=stickers, emoji_list=emojis, mask_position=mask_position)] - + if sticker_format: logger.warning('The parameter "sticker_format" is deprecated since Bot API 7.2. Stickers can now be mixed') @@ -8566,8 +8566,8 @@ async def create_new_sticker_set( async def add_sticker_to_set( self, user_id: int, name: str, emojis: Union[List[str], str]=None, - png_sticker: Optional[Union[Any, str]]=None, - tgs_sticker: Optional[Union[Any, str]]=None, + png_sticker: Optional[Union[Any, str]]=None, + tgs_sticker: Optional[Union[Any, str]]=None, webm_sticker: Optional[Union[Any, str]]=None, mask_position: Optional[types.MaskPosition]=None, sticker: Optional[types.InputSticker]=None) -> bool: @@ -8631,7 +8631,7 @@ async def add_sticker_to_set( async def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: """ Use this method to move a sticker in a set created by the bot to a specific position . Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#setstickerpositioninset :param sticker: File identifier of the sticker @@ -8648,7 +8648,7 @@ async def set_sticker_position_in_set(self, sticker: str, position: int) -> bool async def delete_sticker_from_set(self, sticker: str) -> bool: """ Use this method to delete a sticker from a set created by the bot. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletestickerfromset :param sticker: File identifier of the sticker @@ -8799,9 +8799,9 @@ async def edit_general_forum_topic(self, chat_id: Union[int, str], name: str) -> Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#editgeneralforumtopic - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -8892,7 +8892,7 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: Added additional parameters to support topics, business connections, and message threads. - .. seealso:: + .. seealso:: For more details, visit the `custom_states.py example `_. @@ -8925,7 +8925,7 @@ async def set_state(self, user_id: int, state: Union[int, str, State], chat_id: bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - async def reset_data(self, user_id: int, chat_id: Optional[int]=None, + async def reset_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ @@ -8964,7 +8964,7 @@ async def delete_state(self, user_id: int, chat_id: Optional[int]=None, business :param user_id: User's identifier :type user_id: :obj:`int` - + :param chat_id: Chat's identifier :type chat_id: :obj:`int` @@ -9018,7 +9018,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - async def get_state(self, user_id: int, chat_id: Optional[int]=None, + async def get_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> str: """ @@ -9026,7 +9026,7 @@ async def get_state(self, user_id: int, chat_id: Optional[int]=None, Not recommended to use this method. But it is ok for debugging. .. warning:: - + Even if you are using :class:`telebot.types.State`, this method will return a string. When comparing(not recommended), you should compare this string with :class:`telebot.types.State`.name @@ -9056,9 +9056,9 @@ async def get_state(self, user_id: int, chat_id: Optional[int]=None, bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - async def add_data(self, user_id: int, chat_id: Optional[int]=None, + async def add_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None, **kwargs) -> None: """ From dd3626fbc9468acf75446e5a3061d829d34084f1 Mon Sep 17 00:00:00 2001 From: All-The-Foxes <116322192+All-The-Foxes@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:32:24 -0400 Subject: [PATCH 472/480] Default to None for filter func in inline_handler for sync version --- telebot/__init__.py | 720 ++++++++++++++++++++++---------------------- 1 file changed, 360 insertions(+), 360 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 59a8d7db8..6949842f7 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -46,7 +46,7 @@ REPLY_MARKUP_TYPES = Union[ - types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup, + types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup, types.ReplyKeyboardRemove, types.ForceReply] @@ -93,7 +93,7 @@ class TeleBot: from telebot import TeleBot bot = TeleBot('token') # get token from @BotFather - # now you can register other handlers/update listeners, + # now you can register other handlers/update listeners, # and use bot methods. See more examples in examples/ directory: @@ -139,7 +139,7 @@ class TeleBot: :param use_class_middlewares: Use class middlewares, defaults to False :type use_class_middlewares: :obj:`bool`, optional - + :param disable_web_page_preview: Default value for disable_web_page_preview, defaults to None :type disable_web_page_preview: :obj:`bool`, optional @@ -151,7 +151,7 @@ class TeleBot: :param allow_sending_without_reply: Default value for allow_sending_without_reply, defaults to None :type allow_sending_without_reply: :obj:`bool`, optional - + :param colorful_logs: Outputs colorful logs :type colorful_logs: :obj:`bool`, optional @@ -168,7 +168,7 @@ def __init__( next_step_backend: Optional[HandlerBackend]=None, reply_backend: Optional[HandlerBackend]=None, exception_handler: Optional[ExceptionHandler]=None, last_update_id: Optional[int]=0, suppress_middleware_excepions: Optional[bool]=False, state_storage: Optional[StateStorageBase]=StateMemoryStorage(), - use_class_middlewares: Optional[bool]=False, + use_class_middlewares: Optional[bool]=False, disable_web_page_preview: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -194,7 +194,7 @@ def __init__( if validate_token: util.validate_token(self.token) - + self.bot_id: Union[int, None] = util.extract_bot_id(self.token) # subject to change in future, unspecified # logs-related @@ -292,7 +292,7 @@ def __init__( self.threaded = threaded if self.threaded: self.worker_pool = util.ThreadPool(self, num_threads=num_threads) - + @property def user(self) -> types.User: """ @@ -438,15 +438,15 @@ def set_webhook(self, url: Optional[str]=None, certificate: Optional[Union[str, Defaults to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput, defaults to None :type max_connections: :obj:`int`, optional - + :param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - + Please note that this parameter doesn't affect updates created before the call to the setWebhook, so unwanted updates may be received for a short period of time. Defaults to None - + :type allowed_updates: :obj:`list`, optional :param ip_address: The fixed IP address which will be used to send webhook requests instead of the IP address @@ -516,7 +516,7 @@ def run_webhooks(self, :type max_connections: :obj:`int`, optional :param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] - to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). + to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used. defaults to None :type allowed_updates: :obj:`list`, optional @@ -545,7 +545,7 @@ def run_webhooks(self, if not url_path: url_path = self.token + '/' if url_path[-1] != '/': url_path += '/' - + protocol = "https" if certificate else "http" if not webhook_url: webhook_url = "{}://{}:{}/{}".format(protocol, listen, port, url_path) @@ -627,8 +627,8 @@ def remove_webhook(self) -> bool: return self.set_webhook() # No params resets webhook - def get_updates(self, offset: Optional[int]=None, limit: Optional[int]=None, - timeout: Optional[int]=20, allowed_updates: Optional[List[str]]=None, + def get_updates(self, offset: Optional[int]=None, limit: Optional[int]=None, + timeout: Optional[int]=20, allowed_updates: Optional[List[str]]=None, long_polling_timeout: int=20) -> List[types.Update]: """ Use this method to receive incoming updates using long polling (wiki). An Array of Update objects is returned. @@ -678,14 +678,14 @@ def __retrieve_updates(self, timeout=20, long_polling_timeout=20, allowed_update Registered listeners and applicable message handlers will be notified when a new message arrives. :meta private: - + :raises ApiException when a call has failed. """ if self.skip_pending: self.__skip_updates() logger.debug('Skipped all pending messages') self.skip_pending = False - updates = self.get_updates(offset=(self.last_update_id + 1), + updates = self.get_updates(offset=(self.last_update_id + 1), allowed_updates=allowed_updates, timeout=timeout, long_polling_timeout=long_polling_timeout) self.process_new_updates(updates) @@ -726,7 +726,7 @@ def process_new_updates(self, updates: List[types.Update]): new_edited_business_messages = None new_deleted_business_messages = None new_purchased_paid_media = None - + for update in updates: if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares: try: @@ -810,7 +810,7 @@ def process_new_updates(self, updates: List[types.Update]): if update.purchased_paid_media: if new_purchased_paid_media is None: new_purchased_paid_media = [] new_purchased_paid_media.append(update.purchased_paid_media) - + if new_messages: self.process_new_messages(new_messages) if new_edited_messages: @@ -890,7 +890,7 @@ def process_new_message_reaction(self, new_message_reactions): :meta private: """ self._notify_command_handlers(self.message_reaction_handlers, new_message_reactions, 'message_reaction') - + def process_new_message_reaction_count(self, new_message_reaction_counts): """ :meta private: @@ -938,7 +938,7 @@ def process_new_poll_answer(self, new_poll_answers): :meta private: """ self._notify_command_handlers(self.poll_answer_handlers, new_poll_answers, 'poll_answer') - + def process_new_my_chat_member(self, new_my_chat_members): """ :meta private: @@ -986,13 +986,13 @@ def process_new_edited_business_message(self, new_edited_business_messages): :meta private: """ self._notify_command_handlers(self.edited_business_message_handlers, new_edited_business_messages, 'edited_business_message') - + def process_new_deleted_business_messages(self, new_deleted_business_messages): """ :meta private: """ self._notify_command_handlers(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages') - + def process_new_purchased_paid_media(self, new_purchased_paid_media): """ :meta private: @@ -1047,7 +1047,7 @@ def _setup_change_detector(self, path_to_watch: str): # Make it possible to specify --path argument to the script path = sys.argv[sys.argv.index('--path') + 1] if '--path' in sys.argv else '.' - + self.event_observer = Observer() self.event_observer.schedule(self.event_handler, path, recursive=True) self.event_observer.start() @@ -1066,7 +1066,7 @@ def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[boo Wrap polling with infinite loop and exception handling to avoid bot stops polling. .. note:: - + Install watchdog and psutil before using restart_on_change option. :param timeout: Request connection timeout. @@ -1083,11 +1083,11 @@ def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[boo :type logger_level: :obj:`int`. :param allowed_updates: A list of the update types you want your bot to receive. - For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. - See util.update_types for a complete list of available update types. - Specify an empty list to receive all update types except chat_member (default). + For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. + See util.update_types for a complete list of available update types. + Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - Please note that this parameter doesn't affect updates created before the call to the get_updates, + Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` @@ -1132,14 +1132,14 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F This allows the bot to retrieve Updates automatically and notify listeners and message handlers accordingly. Warning: Do not call this function more than once! - + Always gets updates. .. deprecated:: 4.1.1 Use :meth:`infinity_polling` instead. .. note:: - + Install watchdog and psutil before using restart_on_change option. :param interval: Delay between two update retrivals @@ -1153,7 +1153,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F :param skip_pending: skip old updates :type skip_pending: :obj:`bool` - + :param long_polling_timeout: Timeout in seconds for long polling (see API docs) :type long_polling_timeout: :obj:`int` @@ -1162,12 +1162,12 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F :type logger_level: :obj:`int` :param allowed_updates: A list of the update types you want your bot to receive. - For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. - See util.update_types for a complete list of available update types. - Specify an empty list to receive all update types except chat_member (default). + For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. + See util.update_types for a complete list of available update types. + Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - - Please note that this parameter doesn't affect updates created before the call to the get_updates, + + Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` @@ -1179,7 +1179,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F :param path_to_watch: Path to watch for changes. Defaults to None :type path_to_watch: :obj:`str` - + :return: """ if none_stop is not None: @@ -1193,7 +1193,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F self._setup_change_detector(path_to_watch) logger.info('Starting your bot with username: [@%s]', self.user.username) - + if self.threaded: self.__threaded_polling(non_stop=non_stop, interval=interval, timeout=timeout, long_polling_timeout=long_polling_timeout, logger_level=logger_level, allowed_updates=allowed_updates) @@ -1386,9 +1386,9 @@ def get_me(self) -> types.User: def get_file(self, file_id: Optional[str]) -> types.File: """ Use this method to get basic info about a file and prepare it for downloading. - For the moment, bots can download files of up to 20MB in size. - On success, a File object is returned. - It is guaranteed that the link will be valid for at least 1 hour. + For the moment, bots can download files of up to 20MB in size. + On success, a File object is returned. + It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can be requested by calling get_file again. Telegram documentation: https://core.telegram.org/bots/api#getfile @@ -1431,11 +1431,11 @@ def download_file(self, file_path: str) -> bytes: def log_out(self) -> bool: """ - Use this method to log out from the cloud Bot API server before launching the bot locally. + Use this method to log out from the cloud Bot API server before launching the bot locally. You MUST log out the bot before running it locally, otherwise there is no guarantee that the bot will receive updates. - After a successful call, you can immediately log in on a local server, - but will not be able to log in back to the cloud Bot API server for 10 minutes. + After a successful call, you can immediately log in on a local server, + but will not be able to log in back to the cloud Bot API server for 10 minutes. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#logout @@ -1444,14 +1444,14 @@ def log_out(self) -> bool: :rtype: :obj:`bool` """ return apihelper.log_out(self.token) - - + + def close(self) -> bool: """ - Use this method to close the bot instance before moving it from one local server to another. + Use this method to close the bot instance before moving it from one local server to another. You need to delete the webhook before calling this method to ensure that the bot isn't launched again after server restart. - The method will return error 429 in the first 10 minutes after the bot is launched. + The method will return error 429 in the first 10 minutes after the bot is launched. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#close @@ -1459,10 +1459,10 @@ def close(self) -> bool: :return: :obj:`bool` """ return apihelper.close(self.token) - + def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: """ - Use this method to change the chosen reactions on a message. + 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. Returns True on success. @@ -1487,7 +1487,7 @@ def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reacti self.token, chat_id, message_id, reaction = reaction, is_big = is_big) - def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, + def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, limit: Optional[int]=None) -> types.UserProfilePhotos: """ Use this method to get a list of profile pictures for a user. @@ -1531,7 +1531,7 @@ def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Opti """ return apihelper.set_user_emoji_status( self.token, user_id, emoji_status_custom_emoji_id=emoji_status_custom_emoji_id, emoji_status_expiration_date=emoji_status_expiration_date) - + def get_chat(self, chat_id: Union[int, str]) -> types.ChatFullInfo: """ @@ -1571,7 +1571,7 @@ def get_chat_administrators(self, chat_id: Union[int, str]) -> List[types.ChatMe On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. - Telegram documentation: https://core.telegram.org/bots/api#getchatadministrators + Telegram documentation: https://core.telegram.org/bots/api#getchatadministrators :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) @@ -1623,7 +1623,7 @@ def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str) Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#setchatstickerset :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -1643,7 +1643,7 @@ def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletechatstickerset :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -1658,7 +1658,7 @@ def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatMember: """ Use this method to get information about a member of a chat. Returns a ChatMember object on success. - + Telegram documentation: https://core.telegram.org/bots/api#getchatmember :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -1676,11 +1676,11 @@ def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatM def send_message( - self, chat_id: Union[int, str], text: str, - parse_mode: Optional[str]=None, + self, chat_id: Union[int, str], text: str, + parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -1696,7 +1696,7 @@ def send_message( Use this method to send text messages. Warning: Do not send more than about 4096 characters each message, otherwise you'll risk an HTTP 414 error. - If you must send more than 4096 characters, + If you must send more than 4096 characters, use the `split_string` or `smart_split` function in util.py. Telegram documentation: https://core.telegram.org/bots/api#sendmessage @@ -1806,7 +1806,7 @@ def send_message( def forward_message( - self, chat_id: Union[int, str], from_chat_id: Union[int, str], + self, chat_id: Union[int, str], from_chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, @@ -1855,13 +1855,13 @@ def forward_message( def copy_message( - self, chat_id: Union[int, str], - from_chat_id: Union[int, str], - message_id: int, - caption: Optional[str]=None, - parse_mode: Optional[str]=None, + self, chat_id: Union[int, str], + from_chat_id: Union[int, str], + message_id: int, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -1933,11 +1933,11 @@ def copy_message( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` - + :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` """ - + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification parse_mode = self.parse_mode if (parse_mode is None) else parse_mode protect_content = self.protect_content if (protect_content is None) else protect_content @@ -1969,7 +1969,7 @@ def copy_message( video_start_timestamp=video_start_timestamp)) - def delete_message(self, chat_id: Union[int, str], message_id: int, + def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: """ Use this method to delete a message, including service messages, with the following limitations: @@ -1998,7 +1998,7 @@ def delete_message(self, chat_id: Union[int, str], message_id: int, """ return apihelper.delete_message(self.token, chat_id, message_id, timeout=timeout) - + def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they are skipped. @@ -2016,7 +2016,7 @@ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ return apihelper.delete_messages(self.token, chat_id, message_ids) - + def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: @@ -2058,7 +2058,7 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in protect_content=protect_content) return [types.MessageID.de_json(message_id) for message_id in result] - + def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: @@ -2103,7 +2103,7 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) return [types.MessageID.de_json(message_id) for message_id in result] - + def send_checklist( self, business_connection_id: str, chat_id: Union[int, str], checklist: types.InputChecklist, @@ -2147,7 +2147,7 @@ def send_checklist( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply @@ -2156,7 +2156,7 @@ def send_checklist( self.token, business_connection_id, chat_id, checklist, disable_notification=disable_notification, protect_content=protect_content, message_effect_id=message_effect_id, reply_parameters=reply_parameters, reply_markup=reply_markup)) - + def edit_message_checklist( self, business_connection_id: str, chat_id: Union[int, str], message_id: int, checklist: types.InputChecklist, @@ -2191,9 +2191,9 @@ def edit_message_checklist( def send_dice( self, chat_id: Union[int, str], - emoji: Optional[str]=None, disable_notification: Optional[bool]=None, + emoji: Optional[str]=None, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, @@ -2284,7 +2284,7 @@ def send_dice( def send_photo( - self, chat_id: Union[int, str], photo: Union[Any, str], + self, chat_id: Union[int, str], photo: Union[Any, str], caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, @@ -2304,7 +2304,7 @@ def send_photo( Use this method to send photos. On success, the sent Message is returned. Telegram documentation: https://core.telegram.org/bots/api#sendphoto - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2363,7 +2363,7 @@ def send_photo( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` - + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2400,14 +2400,14 @@ def send_photo( def send_audio( - self, chat_id: Union[int, str], audio: Union[Any, str], - caption: Optional[str]=None, duration: Optional[int]=None, + self, chat_id: Union[int, str], audio: Union[Any, str], + caption: Optional[str]=None, duration: Optional[int]=None, performer: Optional[str]=None, title: Optional[str]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -2426,7 +2426,7 @@ def send_audio( For sending voice messages, use the send_voice method instead. Telegram documentation: https://core.telegram.org/bots/api#sendaudio - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2536,12 +2536,12 @@ def send_audio( def send_voice( - self, chat_id: Union[int, str], voice: Union[Any, str], - caption: Optional[str]=None, duration: Optional[int]=None, + self, chat_id: Union[int, str], voice: Union[Any, str], + caption: Optional[str]=None, duration: Optional[int]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, - disable_notification: Optional[bool]=None, + parse_mode: Optional[str]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -2555,7 +2555,7 @@ def send_voice( Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. Telegram documentation: https://core.telegram.org/bots/api#sendvoice - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2648,11 +2648,11 @@ def send_voice( def send_document( self, chat_id: Union[int, str], document: Union[Any, str], reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - caption: Optional[str]=None, + caption: Optional[str]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, - disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + parse_mode: Optional[str]=None, + disable_notification: Optional[bool]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -2669,7 +2669,7 @@ def send_document( Use this method to send general files. Telegram documentation: https://core.telegram.org/bots/api#senddocument - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2883,7 +2883,7 @@ def send_sticker( if data and (not sticker): logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data - + return types.Message.de_json( apihelper.send_data( self.token, chat_id, sticker, 'sticker', @@ -2895,15 +2895,15 @@ def send_sticker( def send_video( - self, chat_id: Union[int, str], video: Union[Any, str], + self, chat_id: Union[int, str], video: Union[Any, str], duration: Optional[int]=None, width: Optional[int]=None, height: Optional[int]=None, - thumbnail: Optional[Union[Any, str]]=None, - caption: Optional[str]=None, - parse_mode: Optional[str]=None, + thumbnail: Optional[Union[Any, str]]=None, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - supports_streaming: Optional[bool]=None, + supports_streaming: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility @@ -2923,7 +2923,7 @@ def send_video( start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). - + Telegram documentation: https://core.telegram.org/bots/api#sendvideo :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -2953,7 +2953,7 @@ def send_video( :param start_timestamp: Start timestamp for the video in the message :type start_timestamp: :obj:`int` - + :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -3061,19 +3061,19 @@ def send_video( def send_animation( - self, chat_id: Union[int, str], animation: Union[Any, str], + self, chat_id: Union[int, str], animation: Union[Any, str], duration: Optional[int]=None, width: Optional[int]=None, height: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, - caption: Optional[str]=None, + caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, @@ -3086,7 +3086,7 @@ def send_animation( """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. - + Telegram documentation: https://core.telegram.org/bots/api#sendanimation :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -3104,7 +3104,7 @@ def send_animation( :param height: Animation height :type height: :obj:`int` - + :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, @@ -3206,13 +3206,13 @@ def send_animation( def send_video_note( - self, chat_id: Union[int, str], data: Union[Any, str], - duration: Optional[int]=None, + self, chat_id: Union[int, str], data: Union[Any, str], + duration: Optional[int]=None, length: Optional[int]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + disable_notification: Optional[bool]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, @@ -3227,10 +3227,10 @@ def send_video_note( Use this method to send video messages. On success, the sent Message is returned. Telegram documentation: https://core.telegram.org/bots/api#sendvideonote - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - + :param data: Video note to send. Pass a file_id as String to send a video note that exists on the Telegram servers (recommended) or upload a new video using multipart/form-data. Sending video notes by a URL is currently unsupported :type data: :obj:`str` or :class:`telebot.types.InputFile` @@ -3261,7 +3261,7 @@ def send_video_note( :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, - so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . + so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -3321,7 +3321,7 @@ def send_video_note( protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) - + def send_paid_media( self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, @@ -3392,11 +3392,11 @@ def send_paid_media( def send_media_group( - self, chat_id: Union[int, str], + self, chat_id: Union[int, str], media: List[Union[ - types.InputMediaAudio, types.InputMediaDocument, + types.InputMediaAudio, types.InputMediaDocument, types.InputMediaPhoto, types.InputMediaVideo]], - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, @@ -3409,7 +3409,7 @@ def send_media_group( """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. - + Telegram documentation: https://core.telegram.org/bots/api#sendmediagroup :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -3487,17 +3487,17 @@ def send_media_group( def send_location( - self, chat_id: Union[int, str], - latitude: float, longitude: float, + self, chat_id: Union[int, str], + latitude: float, longitude: float, live_period: Optional[int]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, - horizontal_accuracy: Optional[float]=None, - heading: Optional[int]=None, + horizontal_accuracy: Optional[float]=None, + heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, @@ -3601,14 +3601,14 @@ def send_location( def edit_message_live_location( - self, latitude: float, longitude: float, - chat_id: Optional[Union[int, str]]=None, + self, latitude: float, longitude: float, + chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, - horizontal_accuracy: Optional[float]=None, - heading: Optional[int]=None, + horizontal_accuracy: Optional[float]=None, + heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, live_period: Optional[int]=None, business_connection_id: Optional[str]=None @@ -3669,9 +3669,9 @@ def edit_message_live_location( def stop_message_live_location( - self, chat_id: Optional[Union[int, str]]=None, + self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: @@ -3680,7 +3680,7 @@ def stop_message_live_location( On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. Telegram documentation: https://core.telegram.org/bots/api#stopmessagelivelocation - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -3711,14 +3711,14 @@ def stop_message_live_location( def send_venue( - self, chat_id: Union[int, str], - latitude: Optional[float], longitude: Optional[float], - title: str, address: str, - foursquare_id: Optional[str]=None, + self, chat_id: Union[int, str], + latitude: Optional[float], longitude: Optional[float], + title: str, address: str, + foursquare_id: Optional[str]=None, foursquare_type: Optional[str]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility google_place_id: Optional[str]=None, @@ -3731,12 +3731,12 @@ def send_venue( allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. - + Telegram documentation: https://core.telegram.org/bots/api#sendvenue :param chat_id: Unique identifier for the target chat or username of the target channel :type chat_id: :obj:`int` or :obj:`str` - + :param latitude: Latitude of the venue :type latitude: :obj:`float` @@ -3833,12 +3833,12 @@ def send_venue( def send_contact( - self, chat_id: Union[int, str], phone_number: str, - first_name: str, last_name: Optional[str]=None, + self, chat_id: Union[int, str], phone_number: str, + first_name: str, last_name: Optional[str]=None, vcard: Optional[str]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, @@ -3950,7 +3950,7 @@ def send_chat_action( :param chat_id: Unique identifier for the target chat or username of the target channel :type chat_id: :obj:`int` or :obj:`str` - + :param action: Type of action to broadcast. Choose one, depending on what the user is about to receive: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_voice or upload_voice for voice notes, upload_document for general files, @@ -3972,11 +3972,11 @@ def send_chat_action( return apihelper.send_chat_action( self.token, chat_id, action, timeout=timeout, message_thread_id=message_thread_id, business_connection_id=business_connection_id) - + @util.deprecated(deprecation_text="Use ban_chat_member instead") def kick_chat_member( - self, chat_id: Union[int, str], user_id: int, - until_date:Optional[Union[int, datetime]]=None, + self, chat_id: Union[int, str], user_id: int, + until_date:Optional[Union[int, datetime]]=None, revoke_messages: Optional[bool]=None) -> bool: """ This function is deprecated. Use `ban_chat_member` instead. @@ -3986,13 +3986,13 @@ def kick_chat_member( def ban_chat_member( - self, chat_id: Union[int, str], user_id: int, - until_date: Optional[Union[int, datetime]]=None, + self, chat_id: Union[int, str], user_id: int, + until_date: Optional[Union[int, datetime]]=None, revoke_messages: Optional[bool]=None) -> bool: """ - Use this method to ban a user in a group, a supergroup or a channel. - In the case of supergroups and channels, the user will not be able to return to the chat on their - own using invite links, etc., unless unbanned first. + Use this method to ban a user in a group, a supergroup or a channel. + In the case of supergroups and channels, the user will not be able to return to the chat on their + own using invite links, etc., unless unbanned first. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#banchatmember @@ -4009,10 +4009,10 @@ def ban_chat_member( :type until_date: :obj:`int` or :obj:`datetime` :param revoke_messages: Pass True to delete all messages from the chat for the user that is being removed. - If False, the user will be able to see messages in the group that were sent before the user was removed. + If False, the user will be able to see messages in the group that were sent before the user was removed. Always True for supergroups and channels. :type revoke_messages: :obj:`bool` - + :return: Returns True on success. :rtype: :obj:`bool` """ @@ -4021,7 +4021,7 @@ def ban_chat_member( def unban_chat_member( - self, chat_id: Union[int, str], user_id: int, + self, chat_id: Union[int, str], user_id: int, only_if_banned: Optional[bool]=False) -> bool: """ Use this method to unban a previously kicked user in a supergroup or channel. @@ -4049,15 +4049,15 @@ def unban_chat_member( def restrict_chat_member( - self, chat_id: Union[int, str], user_id: int, + self, chat_id: Union[int, str], user_id: int, until_date: Optional[Union[int, datetime]]=None, - can_send_messages: Optional[bool]=None, + can_send_messages: Optional[bool]=None, can_send_media_messages: Optional[bool]=None, - can_send_polls: Optional[bool]=None, + can_send_polls: Optional[bool]=None, can_send_other_messages: Optional[bool]=None, - can_add_web_page_previews: Optional[bool]=None, + can_add_web_page_previews: Optional[bool]=None, can_change_info: Optional[bool]=None, - can_invite_users: Optional[bool]=None, + can_invite_users: Optional[bool]=None, can_pin_messages: Optional[bool]=None, permissions: Optional[types.ChatPermissions]=None, use_independent_chat_permissions: Optional[bool]=None) -> bool: @@ -4085,10 +4085,10 @@ def restrict_chat_member( :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` - + :param can_send_media_messages: deprecated :type can_send_media_messages: :obj:`bool` - + :param can_send_polls: deprecated :type can_send_polls: :obj:`bool` @@ -4139,16 +4139,16 @@ def restrict_chat_member( def promote_chat_member( self, chat_id: Union[int, str], user_id: int, - can_change_info: Optional[bool]=None, + can_change_info: Optional[bool]=None, can_post_messages: Optional[bool]=None, - can_edit_messages: Optional[bool]=None, - can_delete_messages: Optional[bool]=None, + can_edit_messages: Optional[bool]=None, + can_delete_messages: Optional[bool]=None, can_invite_users: Optional[bool]=None, - can_restrict_members: Optional[bool]=None, - can_pin_messages: Optional[bool]=None, + can_restrict_members: Optional[bool]=None, + can_pin_messages: Optional[bool]=None, can_promote_members: Optional[bool]=None, - is_anonymous: Optional[bool]=None, - can_manage_chat: Optional[bool]=None, + is_anonymous: Optional[bool]=None, + can_manage_chat: Optional[bool]=None, can_manage_video_chats: Optional[bool]=None, can_manage_voice_chats: Optional[bool]=None, can_manage_topics: Optional[bool]=None, @@ -4198,9 +4198,9 @@ def promote_chat_member( :param is_anonymous: Pass True, if the administrator's presence in the chat is hidden :type is_anonymous: :obj:`bool` - :param can_manage_chat: Pass True, if the administrator can access the chat event log, chat statistics, - message statistics in channels, see channel members, - see anonymous administrators in supergroups and ignore slow mode. + :param can_manage_chat: Pass True, if the administrator can access the chat event log, chat statistics, + message statistics in channels, see channel members, + see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege :type can_manage_chat: :obj:`bool` @@ -4267,14 +4267,14 @@ def set_chat_administrator_custom_title( """ return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title) - + def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ Use this method to ban a channel chat in a supergroup or a channel. - The owner of the chat will not be able to send messages and join live - streams on behalf of the chat, unless it is unbanned first. - The bot must be an administrator in the supergroup or channel - for this to work and must have the appropriate administrator rights. + The owner of the chat will not be able to send messages and join live + streams on behalf of the chat, unless it is unbanned first. + The bot must be an administrator in the supergroup or channel + for this to work and must have the appropriate administrator rights. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#banchatsenderchat @@ -4293,8 +4293,8 @@ def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[i def unban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ - Use this method to unban a previously banned channel chat in a supergroup or channel. - The bot must be an administrator for this to work and must have the appropriate + Use this method to unban a previously banned channel chat in a supergroup or channel. + The bot must be an administrator for this to work and must have the appropriate administrator rights. Returns True on success. @@ -4345,7 +4345,7 @@ def set_chat_permissions( def create_chat_invite_link( self, chat_id: Union[int, str], name: Optional[str]=None, - expire_date: Optional[Union[int, datetime]]=None, + expire_date: Optional[Union[int, datetime]]=None, member_limit: Optional[int]=None, creates_join_request: Optional[bool]=None) -> types.ChatInviteLink: """ @@ -4432,7 +4432,7 @@ def create_chat_subscription_invite_link( :param chat_id: Unique identifier for the target channel chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - + :param name: Invite link name; 0-32 characters :type name: :obj:`str` @@ -4450,7 +4450,7 @@ def create_chat_subscription_invite_link( return types.ChatInviteLink.de_json( apihelper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name=name) ) - + def edit_chat_subscription_invite_link( self, chat_id: Union[int, str], invite_link: str, name: Optional[str]=None) -> types.ChatInviteLink: """ @@ -4480,7 +4480,7 @@ def revoke_chat_invite_link( self, chat_id: Union[int, str], invite_link: str) -> types.ChatInviteLink: """ Use this method to revoke an invite link created by the bot. - Note: If the primary link is revoked, a new link is automatically generated The bot must be an administrator + Note: If the primary link is revoked, a new link is automatically generated The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Telegram documentation: https://core.telegram.org/bots/api#revokechatinvitelink @@ -4519,7 +4519,7 @@ def export_chat_invite_link(self, chat_id: Union[int, str]) -> str: def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ - Use this method to approve a chat join request. + Use this method to approve a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns True on success. @@ -4540,7 +4540,7 @@ def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int def decline_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ - Use this method to decline a chat join request. + Use this method to decline a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns True on success. @@ -4599,21 +4599,21 @@ def delete_chat_photo(self, chat_id: Union[int, str]) -> bool: """ return apihelper.delete_chat_photo(self.token, chat_id) - - def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, + + def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> List[types.BotCommand]: """ - Use this method to get the current list of the bot's commands. + Use this method to get the current list of the bot's commands. Returns List of BotCommand on success. Telegram documentation: https://core.telegram.org/bots/api#getmycommands - :param scope: The scope of users for which the commands are relevant. + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -4641,7 +4641,7 @@ def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=Non """ return apihelper.set_my_name(self.token, name=name, language_code=language_code) - + def get_my_name(self, language_code: Optional[str]=None): """ Use this method to get the current bot name for the given user language. @@ -4680,7 +4680,7 @@ def set_my_description(self, description: Optional[str]=None, language_code: Opt return apihelper.set_my_description( self.token, description=description, language_code=language_code) - + def get_my_description(self, language_code: Optional[str]=None): """ Use this method to get the current bot description for the given user language. @@ -4696,11 +4696,11 @@ def get_my_description(self, language_code: Optional[str]=None): return types.BotDescription.de_json( apihelper.get_my_description(self.token, language_code=language_code)) - + def set_my_short_description(self, short_description:Optional[str]=None, language_code:Optional[str]=None): """ Use this method to change the bot's short description, which is shown on the bot's profile page and - is sent together with the link when users share the bot. + is sent together with the link when users share the bot. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmyshortdescription @@ -4717,7 +4717,7 @@ def set_my_short_description(self, short_description:Optional[str]=None, languag return apihelper.set_my_short_description( self.token, short_description=short_description, language_code=language_code) - + def get_my_short_description(self, language_code: Optional[str]=None): """ Use this method to get the current bot short description for the given user language. @@ -4736,13 +4736,13 @@ def get_my_short_description(self, language_code: Optional[str]=None): def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ - Use this method to change the bot's menu button in a private chat, - or the default menu button. + Use this method to change the bot's menu button in a private chat, + or the default menu button. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setchatmenubutton - :param chat_id: Unique identifier for the target private chat. + :param chat_id: Unique identifier for the target private chat. If not specified, default bot's menu button will be changed. :type chat_id: :obj:`int` or :obj:`str` @@ -4774,13 +4774,13 @@ def get_chat_menu_button(self, chat_id: Union[int, str]=None) -> types.MenuButto apihelper.get_chat_menu_button(self.token, chat_id=chat_id)) - def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, + def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, for_channels: Optional[bool]=None) -> bool: """ Use this method to change the default administrator rights requested by the bot when it's added as an administrator to groups or channels. These rights will be suggested to users, but they are are free to modify - the list before adding the bot. + the list before adding the bot. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmydefaultadministratorrights @@ -4834,8 +4834,8 @@ def get_business_connection(self, business_connection_id: str) -> types.Business return types.BusinessConnection.de_json( apihelper.get_business_connection(self.token, business_connection_id) ) - - + + def set_my_commands(self, commands: List[types.BotCommand], scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> bool: @@ -4847,12 +4847,12 @@ def set_my_commands(self, commands: List[types.BotCommand], :param commands: List of BotCommand. At most 100 commands can be specified. :type commands: :obj:`list` of :class:`telebot.types.BotCommand` - :param scope: The scope of users for which the commands are relevant. + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -4861,22 +4861,22 @@ def set_my_commands(self, commands: List[types.BotCommand], """ return apihelper.set_my_commands(self.token, commands, scope=scope, language_code=language_code) - - def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, + + def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> bool: """ - Use this method to delete the list of the bot's commands for the given scope and user language. - After deletion, higher level commands will be shown to affected users. + Use this method to delete the list of the bot's commands for the given scope and user language. + After deletion, higher level commands will be shown to affected users. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#deletemycommands - - :param scope: The scope of users for which the commands are relevant. + + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -4930,7 +4930,7 @@ def set_chat_description(self, chat_id: Union[int, str], description: Optional[s def pin_chat_message( - self, chat_id: Union[int, str], message_id: int, + self, chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=False, business_connection_id: Optional[str]=None) -> bool: """ Use this method to pin a message in a supergroup. @@ -5005,10 +5005,10 @@ def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: def edit_message_text( - self, text: str, - chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + self, text: str, + chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, + inline_message_id: Optional[str]=None, parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility @@ -5058,7 +5058,7 @@ def edit_message_text( :rtype: :obj:`types.Message` or :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode - + if disable_web_page_preview is not None: # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") @@ -5089,9 +5089,9 @@ def edit_message_text( def edit_message_media( - self, media: Any, chat_id: Optional[Union[int, str]]=None, + self, media: Any, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: @@ -5100,7 +5100,7 @@ def edit_message_media( If a message is part of a message album, then it can be edited only to an audio for audio albums, only to a document for document albums and to a photo or a video otherwise. When an inline message is edited, a new file can't be uploaded; use a previously uploaded file via its file_id or specify a URL. On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. - Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. + Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. Telegram documentation: https://core.telegram.org/bots/api#editmessagemedia @@ -5109,7 +5109,7 @@ def edit_message_media( :param chat_id: Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - :param message_id: Required if inline_message_id is not specified. Identifier of the sent message + :param message_id: Required if inline_message_id is not specified. Identifier of the sent message :type message_id: :obj:`int` :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message @@ -5137,9 +5137,9 @@ def edit_message_media( def edit_message_reply_markup( - self, chat_id: Optional[Union[int, str]]=None, + self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: @@ -5179,10 +5179,10 @@ def edit_message_reply_markup( def send_game( - self, chat_id: Union[int, str], game_short_name: str, + self, chat_id: Union[int, str], game_short_name: str, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, @@ -5273,10 +5273,10 @@ def send_game( def set_game_score( - self, user_id: Union[int, str], score: int, - force: Optional[bool]=None, - chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + self, user_id: Union[int, str], score: int, + force: Optional[bool]=None, + chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None, disable_edit_message: Optional[bool]=None) -> Union[types.Message, bool]: """ @@ -5319,7 +5319,7 @@ def set_game_score( def get_game_high_scores( self, user_id: int, chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None) -> List[types.GameHighScore]: """ Use this method to get data for high score tables. Will return the score of the specified user and several of @@ -5352,20 +5352,20 @@ def get_game_high_scores( def send_invoice( - self, chat_id: Union[int, str], title: str, description: str, - invoice_payload: str, provider_token: Union[str, None], currency: str, - prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, - photo_url: Optional[str]=None, photo_size: Optional[int]=None, + self, chat_id: Union[int, str], title: str, description: str, + invoice_payload: str, provider_token: Union[str, None], currency: str, + prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, + photo_url: Optional[str]=None, photo_size: Optional[int]=None, photo_width: Optional[int]=None, photo_height: Optional[int]=None, - need_name: Optional[bool]=None, need_phone_number: Optional[bool]=None, + need_name: Optional[bool]=None, need_phone_number: Optional[bool]=None, need_email: Optional[bool]=None, need_shipping_address: Optional[bool]=None, - send_phone_number_to_provider: Optional[bool]=None, - send_email_to_provider: Optional[bool]=None, + send_phone_number_to_provider: Optional[bool]=None, + send_email_to_provider: Optional[bool]=None, is_flexible: Optional[bool]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - provider_data: Optional[str]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + provider_data: Optional[str]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility max_tip_amount: Optional[int] = None, @@ -5416,7 +5416,7 @@ def send_invoice( :param photo_size: Photo size in bytes :type photo_size: :obj:`int` - :param photo_width: Photo width + :param photo_width: Photo width :type photo_width: :obj:`int` :param photo_height: Photo height @@ -5530,9 +5530,9 @@ def send_invoice( ) def create_invoice_link(self, - title: str, description: str, payload:str, provider_token: Union[str, None], + title: str, description: str, payload:str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], - max_tip_amount: Optional[int] = None, + max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, provider_data: Optional[str]=None, photo_url: Optional[str]=None, @@ -5548,9 +5548,9 @@ def create_invoice_link(self, is_flexible: Optional[bool]=None, subscription_period: Optional[int]=None, business_connection_id: Optional[str]=None) -> str: - + """ - Use this method to create a link for an invoice. + Use this method to create a link for an invoice. Returns the created invoice link as String on success. Telegram documentation: @@ -5649,17 +5649,17 @@ def create_invoice_link(self, # noinspection PyShadowingBuiltins def send_poll( self, chat_id: Union[int, str], question: str, options: List[Union[str, types.InputPollOption]], - is_anonymous: Optional[bool]=None, type: Optional[str]=None, - allows_multiple_answers: Optional[bool]=None, + is_anonymous: Optional[bool]=None, type: Optional[str]=None, + allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, - explanation: Optional[str]=None, - explanation_parse_mode: Optional[str]=None, - open_period: Optional[int]=None, - close_date: Optional[Union[int, datetime]]=None, + explanation: Optional[str]=None, + explanation_parse_mode: Optional[str]=None, + open_period: Optional[int]=None, + close_date: Optional[Union[int, datetime]]=None, is_closed: Optional[bool]=None, disable_notification: Optional[bool]=False, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, @@ -5816,7 +5816,7 @@ def send_poll( def stop_poll( - self, chat_id: Union[int, str], message_id: int, + self, chat_id: Union[int, str], message_id: int, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None) -> types.Poll: """ @@ -5845,8 +5845,8 @@ def stop_poll( def answer_shipping_query( - self, shipping_query_id: str, ok: bool, - shipping_options: Optional[List[types.ShippingOption]]=None, + self, shipping_query_id: str, ok: bool, + shipping_options: Optional[List[types.ShippingOption]]=None, error_message: Optional[str]=None) -> bool: """ Asks for an answer to a shipping question. @@ -5874,7 +5874,7 @@ def answer_shipping_query( def answer_pre_checkout_query( - self, pre_checkout_query_id: str, ok: bool, + self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str]=None) -> bool: """ Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the @@ -5886,7 +5886,7 @@ def answer_pre_checkout_query( Telegram documentation: https://core.telegram.org/bots/api#answerprecheckoutquery - :param pre_checkout_query_id: Unique identifier for the query to be answered + :param pre_checkout_query_id: Unique identifier for the query to be answered :type pre_checkout_query_id: :obj:`int` :param ok: Specify True if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. Use False if there are any problems. @@ -5902,11 +5902,11 @@ def answer_pre_checkout_query( """ return apihelper.answer_pre_checkout_query( self.token, pre_checkout_query_id, ok, error_message=error_message) - + def get_my_star_balance(self) -> types.StarAmount: """ Returns the bot's current Telegram Stars balance. On success, returns a StarAmount object. - + Telegram documentation: https://core.telegram.org/bots/api#getmystarbalance :return: On success, returns a StarAmount object. @@ -5933,8 +5933,8 @@ def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int] return types.StarTransactions.de_json( apihelper.get_star_transactions(self.token, offset=offset, limit=limit) ) - - + + def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: """ Refunds a successful payment in Telegram Stars. Returns True on success. @@ -5973,10 +5973,10 @@ def edit_user_star_subscription(self, user_id: int, telegram_payment_charge_id: return apihelper.edit_user_star_subscription(self.token, user_id, telegram_payment_charge_id, is_canceled) def edit_message_caption( - self, caption: str, chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + self, caption: str, chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - parse_mode: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, show_caption_above_media: Optional[bool]=None, @@ -6068,12 +6068,12 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message def answer_inline_query( - self, inline_query_id: str, - results: List[Any], - cache_time: Optional[int]=None, - is_personal: Optional[bool]=None, + self, inline_query_id: str, + results: List[Any], + cache_time: Optional[int]=None, + is_personal: Optional[bool]=None, next_offset: Optional[str]=None, - switch_pm_text: Optional[str]=None, + switch_pm_text: Optional[str]=None, switch_pm_parameter: Optional[str]=None, button: Optional[types.InlineQueryResultsButton]=None) -> bool: """ @@ -6120,7 +6120,7 @@ def answer_inline_query( if not button and (switch_pm_text or switch_pm_parameter): logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.") button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter) - + return apihelper.answer_inline_query( self.token, inline_query_id, results, cache_time=cache_time, is_personal=is_personal, next_offset=next_offset, button=button) @@ -6128,7 +6128,7 @@ def answer_inline_query( def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bool: """ - Use this method to clear the list of pinned messages in a General forum topic. + Use this method to clear the list of pinned messages in a General forum topic. The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator right in the supergroup. Returns True on success. @@ -6145,8 +6145,8 @@ def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bo def answer_callback_query( - self, callback_query_id: int, - text: Optional[str]=None, show_alert: Optional[bool]=None, + self, callback_query_id: int, + text: Optional[str]=None, show_alert: Optional[bool]=None, url: Optional[str]=None, cache_time: Optional[int]=None) -> bool: """ Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to @@ -6176,7 +6176,7 @@ def answer_callback_query( return apihelper.answer_callback_query( self.token, callback_query_id, text=text, show_alert=show_alert, url=url, cache_time=cache_time) - + def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts: """ Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. @@ -6199,7 +6199,7 @@ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types. # noinspection PyShadowingBuiltins def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None, format: Optional[str]=None) -> bool: """ - Use this method to set the thumbnail of a sticker set. + Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumbnail @@ -6230,11 +6230,11 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[An return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) - + @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]=None): """ - Use this method to set the thumbnail of a sticker set. + Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumb @@ -6258,7 +6258,7 @@ def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]= def get_sticker_set(self, name: str) -> types.StickerSet: """ Use this method to get a sticker set. On success, a StickerSet object is returned. - + Telegram documentation: https://core.telegram.org/bots/api#getstickerset :param name: Sticker set name @@ -6285,7 +6285,7 @@ def get_custom_emoji_stickers(self, custom_emoji_ids: List[str]) -> List[types.S result = apihelper.get_custom_emoji_stickers(self.token, custom_emoji_ids) return [types.Sticker.de_json(sticker) for sticker in result] - + def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: """ Use this method to change search keywords assigned to a regular or custom emoji sticker. @@ -6303,7 +6303,7 @@ def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: """ return apihelper.set_sticker_keywords(self.token, sticker, keywords=keywords) - + def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosition=None) -> bool: """ Use this method to change the mask position of a mask sticker. @@ -6320,7 +6320,7 @@ def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosit :rtype: :obj:`bool` """ return apihelper.set_sticker_mask_position(self.token, sticker, mask_position=mask_position) - + def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Optional[str]=None) -> bool: """ @@ -6338,7 +6338,7 @@ def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Opt """ return apihelper.set_custom_emoji_sticker_set_thumbnail(self.token, name, custom_emoji_id=custom_emoji_id) - + def set_sticker_set_title(self, name: str, title: str) -> bool: """ Use this method to set the title of a created sticker set. @@ -6355,7 +6355,7 @@ def set_sticker_set_title(self, name: str, title: str) -> bool: """ return apihelper.set_sticker_set_title(self.token, name, title) - + def delete_sticker_set(self, name:str) -> bool: """ Use this method to delete a sticker set. Returns True on success. @@ -6368,7 +6368,7 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None, chat_id: Optional[Union[str, int]] = None) -> bool: """ @@ -6403,13 +6403,13 @@ def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None """ if user_id is None and chat_id is None: raise ValueError("Either user_id or chat_id must be specified.") - + if gift_id is None: raise ValueError("gift_id must be specified.") - + return apihelper.send_gift(self.token, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) - + def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. @@ -6585,12 +6585,12 @@ def set_business_account_gift_settings( :rtype: :obj:`bool` """ return apihelper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) - + def get_business_account_star_balance(self, business_connection_id: str) -> types.StarAmount: """ Returns the amount of Telegram Stars owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns StarAmount on success. - + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountstarbalance :param business_connection_id: Unique identifier of the business connection @@ -6602,7 +6602,7 @@ def get_business_account_star_balance(self, business_connection_id: str) -> type return types.StarAmount.de_json( apihelper.get_business_account_star_balance(self.token, business_connection_id) ) - + def transfer_business_account_stars(self, business_connection_id: str, star_count: int) -> bool: """ Transfers Telegram Stars from the business account balance to the bot's balance. Requires the can_transfer_stars business bot right. Returns True on success. @@ -6619,7 +6619,7 @@ def transfer_business_account_stars(self, business_connection_id: str, star_coun :rtype: :obj:`bool` """ return apihelper.transfer_business_account_stars(self.token, business_connection_id, star_count) - + def get_business_account_gifts( self, business_connection_id: str, exclude_unsaved: Optional[bool]=None, @@ -6632,7 +6632,7 @@ def get_business_account_gifts( limit: Optional[int]=None) -> types.OwnedGifts: """ Returns the gifts received and owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns OwnedGifts on success. - + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountgifts :param business_connection_id: Unique identifier of the business connection @@ -6695,7 +6695,7 @@ def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id: str) :rtype: :obj:`bool` """ return apihelper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) - + def upgrade_gift( self, business_connection_id: str, owned_gift_id: str, keep_original_details: Optional[bool]=None, @@ -6759,7 +6759,7 @@ def transfer_gift( new_owner_chat_id, star_count=star_count ) - + def post_story( self, business_connection_id: str, content: types.InputStoryContent, active_period: int, caption: Optional[str]=None, @@ -6866,7 +6866,7 @@ def edit_story( def delete_story(self, business_connection_id: str, story_id: int) -> bool: """ Deletes a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletestory :param business_connection_id: Unique identifier of the business connection @@ -6915,7 +6915,7 @@ def gift_premium_subscription( text=text, text_parse_mode=text_parse_mode, text_entities=text_entities ) - + def set_business_account_profile_photo( self, business_connection_id: str, photo: types.InputProfilePhoto, is_public: Optional[bool]=None) -> bool: @@ -6994,8 +6994,8 @@ def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, stic :rtype: :obj:`bool` """ return apihelper.replace_sticker_in_set(self.token, user_id, name, old_sticker, sticker) - - + + def set_sticker_emoji_list(self, sticker: str, emoji_list: List[str]) -> bool: """ Use this method to set the emoji list of a custom emoji sticker set. @@ -7017,7 +7017,7 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s """ Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success. - + Telegram documentation: https://core.telegram.org/bots/api#uploadstickerfile :param user_id: User identifier of sticker set owner @@ -7031,7 +7031,7 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s See https://core.telegram.org/stickers for technical requirements. More information on Sending Files » :type sticker: :class:`telebot.types.InputFile` - :param sticker_format: One of "static", "animated", "video". + :param sticker_format: One of "static", "animated", "video". :type sticker_format: :obj:`str` :return: On success, the sent file is returned. @@ -7041,17 +7041,17 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s logger.warning('The parameter "png_sticker" is deprecated. Use "sticker" instead.') sticker = png_sticker sticker_format = "static" - + return types.File.de_json( apihelper.upload_sticker_file(self.token, user_id, sticker, sticker_format) ) def create_new_sticker_set( - self, user_id: int, name: str, title: str, - emojis: Optional[List[str]]=None, - png_sticker: Union[Any, str]=None, - tgs_sticker: Union[Any, str]=None, + self, user_id: int, name: str, title: str, + emojis: Optional[List[str]]=None, + png_sticker: Union[Any, str]=None, + tgs_sticker: Union[Any, str]=None, webm_sticker: Union[Any, str]=None, contains_masks: Optional[bool]=None, sticker_type: Optional[str]=None, @@ -7060,7 +7060,7 @@ def create_new_sticker_set( stickers: List[types.InputSticker]=None, sticker_format: Optional[str]=None) -> bool: """ - Use this method to create new sticker set owned by a user. + Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success. @@ -7124,7 +7124,7 @@ def create_new_sticker_set( sticker_format = 'video' elif png_sticker: sticker_format = 'static' - + if contains_masks is not None: logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type" instead') if sticker_type is None: @@ -7145,8 +7145,8 @@ def create_new_sticker_set( def add_sticker_to_set( self, user_id: int, name: str, emojis: Union[List[str], str], - png_sticker: Optional[Union[Any, str]]=None, - tgs_sticker: Optional[Union[Any, str]]=None, + png_sticker: Optional[Union[Any, str]]=None, + tgs_sticker: Optional[Union[Any, str]]=None, webm_sticker: Optional[Union[Any, str]]=None, mask_position: Optional[types.MaskPosition]=None, sticker: Optional[types.InputSticker]=None) -> bool: @@ -7210,7 +7210,7 @@ def add_sticker_to_set( def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: """ Use this method to move a sticker in a set created by the bot to a specific position . Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#setstickerpositioninset :param sticker: File identifier of the sticker @@ -7228,7 +7228,7 @@ def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: def delete_sticker_from_set(self, sticker: str) -> bool: """ Use this method to delete a sticker from a set created by the bot. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletestickerfromset :param sticker: File identifier of the sticker @@ -7388,9 +7388,9 @@ def edit_general_forum_topic(self, chat_id: Union[int, str], name: str) -> bool: Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#editgeneralforumtopic - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -7473,7 +7473,7 @@ def answer_web_app_query(self, web_app_query_id: str, result: types.InlineQueryR """ Use this method to set the result of an interaction with a Web App and send a corresponding message on behalf of the user to the chat from which - the query originated. + the query originated. On success, a SentWebAppMessage object is returned. Telegram Documentation: https://core.telegram.org/bots/api#answerwebappquery @@ -7541,7 +7541,7 @@ def register_for_reply(self, message: types.Message, callback: Callable, *args, :param args: Optional arguments for the callback function. :param kwargs: Optional keyword arguments for the callback function. - + :return: None """ self.register_for_reply_by_message_id(message.message_id, callback, *args, **kwargs) @@ -7644,8 +7644,8 @@ def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[in Added additional parameters to support topics, business connections, and message threads. - .. seealso:: - + .. seealso:: + For more details, visit the `custom_states.py example `_. :param user_id: User's identifier @@ -7677,7 +7677,7 @@ def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[in bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def reset_data(self, user_id: int, chat_id: Optional[int]=None, + def reset_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ @@ -7720,7 +7720,7 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_conne :param user_id: User's identifier :type user_id: :obj:`int` - + :param chat_id: Chat's identifier :type chat_id: :obj:`int` @@ -7775,7 +7775,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def get_state(self, user_id: int, chat_id: Optional[int]=None, + def get_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> str: """ @@ -7813,9 +7813,9 @@ def get_state(self, user_id: int, chat_id: Optional[int]=None, bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def add_data(self, user_id: int, chat_id: Optional[int]=None, + def add_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None, **kwargs) -> None: """ @@ -7862,7 +7862,7 @@ def register_next_step_handler_by_chat_id( :type callback: :obj:`Callable[[telebot.types.Message], None]` :param args: Args to pass in callback func - + :param kwargs: Args to pass in callback func :return: None @@ -8032,7 +8032,7 @@ def register_middleware_handler(self, callback, update_types=None): bot = TeleBot('TOKEN') bot.register_middleware_handler(print_channel_post_text, update_types=['channel_post', 'edited_channel_post']) - + :param callback: Function that will be used as a middleware handler. :type callback: :obj:`function` @@ -8212,7 +8212,7 @@ def register_message_handler(self, callback: Callable, content_types: Optional[L logger.warning("register_message_handler: 'content_types' filter should be List of strings (content types), not string.") content_types = [content_types] - + handler_dict = self._build_handler_dict(callback, chat_types=chat_types, @@ -8284,7 +8284,7 @@ def add_edited_message_handler(self, handler_dict): """ Adds the edit message handler Note that you should use register_edited_message_handler to add edited_message_handler to the bot. - + :meta private: :param handler_dict: @@ -8406,7 +8406,7 @@ def add_channel_post_handler(self, handler_dict): Note that you should use register_channel_post_handler to add channel_post_handler to the bot. :meta private: - + :param handler_dict: :return: """ @@ -8626,7 +8626,7 @@ def register_message_reaction_handler(self, callback: Callable, func: Callable=N :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) :type pass_bot: :obj:`bool` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -8654,7 +8654,7 @@ def decorator(handler): return decorator - + def add_message_reaction_count_handler(self, handler_dict): """ Adds message reaction count handler @@ -8680,7 +8680,7 @@ def register_message_reaction_count_handler(self, callback: Callable, func: Call :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) :type pass_bot: :obj:`bool` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -8689,7 +8689,7 @@ def register_message_reaction_count_handler(self, callback: Callable, func: Call self.add_message_reaction_count_handler(handler_dict) - def inline_handler(self, func, **kwargs): + def inline_handler(self, func=None, **kwargs): """ Handles new incoming inline query. As a parameter to the decorator function, it passes :class:`telebot.types.InlineQuery` object. @@ -8751,7 +8751,7 @@ def chosen_inline_handler(self, func, **kwargs): :param func: Function executed as a filter :type func: :obj:`function` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -8807,7 +8807,7 @@ def callback_query_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -8861,7 +8861,7 @@ def shipping_query_handler(self, func, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -8938,7 +8938,7 @@ def add_pre_checkout_query_handler(self, handler_dict): """ self.pre_checkout_query_handlers.append(handler_dict) - + def register_pre_checkout_query_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers pre-checkout request handler. @@ -8973,9 +8973,9 @@ def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) self.add_purchased_paid_media_handler(handler_dict) return handler - + return decorator - + def add_purchased_paid_media_handler(self, handler_dict): """ Adds a purchased paid media handler @@ -8994,7 +8994,7 @@ def register_purchased_paid_media_handler(self, callback: Callable, func: Callab :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -9071,7 +9071,7 @@ def poll_answer_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -9238,7 +9238,7 @@ def chat_join_request_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -9286,7 +9286,7 @@ def register_chat_join_request_handler( def chat_boost_handler(self, func=None, **kwargs): """ - Handles new incoming chat boost state. + Handles new incoming chat boost state. it passes :class:`telebot.types.ChatBoostUpdated` object. :param func: Function executed as a filter @@ -9323,7 +9323,7 @@ def register_chat_boost_handler( :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -9339,7 +9339,7 @@ def register_chat_boost_handler( def removed_chat_boost_handler(self, func=None, **kwargs): """ - Handles new incoming chat boost state. + Handles new incoming chat boost state. it passes :class:`telebot.types.ChatBoostRemoved` object. :param func: Function executed as a filter @@ -9355,7 +9355,7 @@ def decorator(handler): return decorator - + def add_removed_chat_boost_handler(self, handler_dict): """ Adds a removed_chat_boost handler. @@ -9376,7 +9376,7 @@ def register_removed_chat_boost_handler( :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -9404,7 +9404,7 @@ def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) self.add_business_connection_handler(handler_dict) return handler - + return decorator @@ -9572,7 +9572,7 @@ def register_business_message_handler(self, :return: None """ - handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, + handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, pass_bot=pass_bot, **kwargs) self.add_business_message_handler(handler_dict) @@ -9632,7 +9632,7 @@ def add_edited_business_message_handler(self, handler_dict): """ Adds the edit message handler Note that you should use register_edited_business_message_handler to add edited_business_message_handler to the bot. - + :meta private: :param handler_dict: @@ -9709,7 +9709,7 @@ def decorator(handler): self.add_deleted_business_messages_handler(handler_dict) return handler - + return decorator @@ -9829,7 +9829,7 @@ def _get_middlewares(self, update_type): :return: """ middlewares = None - if self.middlewares: + if self.middlewares: middlewares = [i for i in self.middlewares if update_type in i.update_types] return middlewares From d113d0205e7c8250f9e9da6deca7840e8e10237a Mon Sep 17 00:00:00 2001 From: All-The-Foxes <116322192+All-The-Foxes@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:47:02 -0400 Subject: [PATCH 473/480] fix line break, fix poll option IDs are not optional --- telebot/types.py | 1189 +++++++++++++++++++++++++--------------------- 1 file changed, 641 insertions(+), 548 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index 971f5824c..27d6c3f22 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -95,7 +95,7 @@ def check_json(json_type, dict_copy = True): If it is not, it is converted to a dict by means of json.loads(json_type) :meta private: - + :param json_type: input json or parsed dict :param dict_copy: if dict is passed and it is changed outside - should be True! :return: Dictionary parsed from json or original dict @@ -121,9 +121,9 @@ class Update(JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#update - :param update_id: The update's unique identifier. Update identifiers start from a certain positive number and - increase sequentially. This ID becomes especially handy if you're using webhooks, since it allows you to ignore - repeated updates or to restore the correct update sequence, should they get out of order. If there are no new updates + :param update_id: The update's unique identifier. Update identifiers start from a certain positive number and + increase sequentially. This ID becomes especially handy if you're using webhooks, since it allows you to ignore + repeated updates or to restore the correct update sequence, should they get out of order. If there are no new updates for at least a week, then identifier of the next update will be chosen randomly instead of sequentially. :type update_id: :obj:`int` @@ -150,8 +150,8 @@ class Update(JsonDeserializable): :param inline_query: Optional. New incoming inline query :type inline_query: :class:`telebot.types.InlineQuery` - :param chosen_inline_result: Optional. The result of an inline query that was chosen by a user and sent to their chat - partner. Please see our documentation on the feedback collecting for details on how to enable these updates for your + :param chosen_inline_result: Optional. The result of an inline query that was chosen by a user and sent to their chat + partner. Please see our documentation on the feedback collecting for details on how to enable these updates for your bot. :type chosen_inline_result: :class:`telebot.types.ChosenInlineResult` @@ -161,30 +161,30 @@ class Update(JsonDeserializable): :param shipping_query: Optional. New incoming shipping query. Only for invoices with flexible price :type shipping_query: :class:`telebot.types.ShippingQuery` - :param pre_checkout_query: Optional. New incoming pre-checkout query. Contains full information about + :param pre_checkout_query: Optional. New incoming pre-checkout query. Contains full information about checkout :type pre_checkout_query: :class:`telebot.types.PreCheckoutQuery` :purchased_paid_media: Optional. A user purchased paid media with a non-empty payload sent by the bot in a non-channel chat :type purchased_paid_media: :class:`telebot.types.PaidMediaPurchased` - :param poll: Optional. New poll state. Bots receive only updates about stopped polls and polls, which are sent by the + :param poll: Optional. New poll state. Bots receive only updates about stopped polls and polls, which are sent by the bot :type poll: :class:`telebot.types.Poll` - :param poll_answer: Optional. A user changed their answer in a non-anonymous poll. Bots receive new votes only in + :param poll_answer: Optional. A user changed their answer in a non-anonymous poll. Bots receive new votes only in polls that were sent by the bot itself. :type poll_answer: :class:`telebot.types.PollAnswer` - :param my_chat_member: Optional. The bot's chat member status was updated in a chat. For private chats, this update + :param my_chat_member: Optional. The bot's chat member status was updated in a chat. For private chats, this update is received only when the bot is blocked or unblocked by the user. :type my_chat_member: :class:`telebot.types.ChatMemberUpdated` - :param chat_member: Optional. A chat member's status was updated in a chat. The bot must be an administrator in the + :param chat_member: Optional. A chat member's status was updated in a chat. The bot must be an administrator in the chat and must explicitly specify “chat_member” in the list of allowed_updates to receive these updates. :type chat_member: :class:`telebot.types.ChatMemberUpdated` - :param chat_join_request: Optional. A request to join the chat has been sent. The bot must have the + :param chat_join_request: Optional. A request to join the chat has been sent. The bot must have the can_invite_users administrator right in the chat to receive these updates. :type chat_join_request: :class:`telebot.types.ChatJoinRequest` @@ -276,7 +276,6 @@ def __init__(self, update_id, message, edited_message, channel_post, edited_chan self.purchased_paid_media: Optional[PaidMediaPurchased] = purchased_paid_media - class ChatMemberUpdated(JsonDeserializable): """ This object represents changes in the status of a chat member. @@ -298,7 +297,7 @@ class ChatMemberUpdated(JsonDeserializable): :param new_chat_member: New information about the chat member :type new_chat_member: :class:`telebot.types.ChatMember` - :param invite_link: Optional. Chat invite link, which was used by the user to join the chat; for joining by invite + :param invite_link: Optional. Chat invite link, which was used by the user to join the chat; for joining by invite link events only. :type invite_link: :class:`telebot.types.ChatInviteLink` @@ -321,7 +320,7 @@ def de_json(cls, json_string): obj['new_chat_member'] = ChatMember.de_json(obj['new_chat_member']) obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link')) return cls(**obj) - + def __init__(self, chat, from_user, date, old_chat_member, new_chat_member, invite_link=None, via_join_request=None, via_chat_folder_invite_link=None, **kwargs): @@ -353,7 +352,7 @@ def difference(self) -> Dict[str, List]: if new[key] != old[key]: dif[key] = [old[key], new[key]] return dif - + class ChatJoinRequest(JsonDeserializable): """ @@ -394,7 +393,7 @@ def de_json(cls, json_string): obj['from_user'] = User.de_json(obj['from']) obj['invite_link'] = ChatInviteLink.de_json(obj.get('invite_link')) return cls(**obj) - + def __init__(self, chat, from_user, user_chat_id, date, bio=None, invite_link=None, **kwargs): self.chat: Chat = chat self.from_user: User = from_user @@ -403,6 +402,7 @@ def __init__(self, chat, from_user, user_chat_id, date, bio=None, invite_link=No self.invite_link: Optional[ChatInviteLink] = invite_link self.user_chat_id: int = user_chat_id + class WebhookInfo(JsonDeserializable): """ Describes the current status of a webhook. @@ -421,23 +421,23 @@ class WebhookInfo(JsonDeserializable): :param ip_address: Optional. Currently used webhook IP address :type ip_address: :obj:`str` - :param last_error_date: Optional. Unix time for the most recent error that happened when trying to deliver an + :param last_error_date: Optional. Unix time for the most recent error that happened when trying to deliver an update via webhook :type last_error_date: :obj:`int` - :param last_error_message: Optional. Error message in human-readable format for the most recent error that + :param last_error_message: Optional. Error message in human-readable format for the most recent error that happened when trying to deliver an update via webhook :type last_error_message: :obj:`str` - :param last_synchronization_error_date: Optional. Unix time of the most recent error that happened when trying + :param last_synchronization_error_date: Optional. Unix time of the most recent error that happened when trying to synchronize available updates with Telegram datacenters :type last_synchronization_error_date: :obj:`int` - :param max_connections: Optional. The maximum allowed number of simultaneous HTTPS connections to the webhook + :param max_connections: Optional. The maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery :type max_connections: :obj:`int` - :param allowed_updates: Optional. A list of update types the bot is subscribed to. Defaults to all update types + :param allowed_updates: Optional. A list of update types the bot is subscribed to. Defaults to all update types except chat_member :type allowed_updates: :obj:`list` of :obj:`str` @@ -450,7 +450,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - def __init__(self, url, has_custom_certificate, pending_update_count, ip_address=None, + def __init__(self, url, has_custom_certificate, pending_update_count, ip_address=None, last_error_date=None, last_error_message=None, last_synchronization_error_date=None, max_connections=None, allowed_updates=None, **kwargs): self.url: str = url @@ -470,8 +470,8 @@ class User(JsonDeserializable, Dictionaryable, JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#user - :param id: Unique identifier for this user or bot. This number may have more than 32 significant bits and some - programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant + :param id: Unique identifier for this user or bot. This number may have more than 32 significant bits and some + programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a 64-bit integer or double-precision float type are safe for storing this identifier. :type id: :obj:`int` @@ -499,7 +499,7 @@ class User(JsonDeserializable, Dictionaryable, JsonSerializable): :param can_join_groups: Optional. True, if the bot can be invited to groups. Returned only in getMe. :type can_join_groups: :obj:`bool` - :param can_read_all_group_messages: Optional. True, if privacy mode is disabled for the bot. Returned only in + :param can_read_all_group_messages: Optional. True, if privacy mode is disabled for the bot. Returned only in getMe. :type can_read_all_group_messages: :obj:`bool` @@ -523,8 +523,8 @@ def de_json(cls, json_string): # noinspection PyShadowingBuiltins def __init__(self, id, is_bot, first_name, last_name=None, username=None, language_code=None, - can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, - is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, + can_join_groups=None, can_read_all_group_messages=None, supports_inline_queries=None, + is_premium=None, added_to_attachment_menu=None, can_connect_to_business=None, has_main_web_app=None, **kwargs): self.id: int = id self.is_bot: bool = is_bot @@ -592,8 +592,8 @@ class ChatFullInfo(JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#chat - :param id: Unique identifier for this chat. This number may have more than 32 significant bits and some programming - languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed + :param id: Unique identifier for this chat. This number may have more than 32 significant bits and some programming + languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. :type id: :obj:`int` @@ -729,9 +729,9 @@ class ChatFullInfo(JsonDeserializable): Custom emoji from this set can be used by all users and bots in the group. Returned only in getChat. :param custom_emoji_sticker_set_name: :obj:`str` - :param linked_chat_id: Optional. Unique identifier for the linked chat, i.e. the discussion group identifier for - a channel and vice versa; for supergroups and channel chats. This identifier may be greater than 32 bits and some - programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a + :param linked_chat_id: Optional. Unique identifier for the linked chat, i.e. the discussion group identifier for + a channel and vice versa; for supergroups and channel chats. This identifier may be greater than 32 bits and some + programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. Returned only in getChat. :type linked_chat_id: :obj:`int` @@ -771,17 +771,17 @@ def de_json(cls, json_string): def __init__(self, id, type, title=None, username=None, first_name=None, last_name=None, photo=None, bio=None, has_private_forwards=None, - description=None, invite_link=None, pinned_message=None, + description=None, invite_link=None, pinned_message=None, permissions=None, slow_mode_delay=None, message_auto_delete_time=None, has_protected_content=None, sticker_set_name=None, - can_set_sticker_set=None, linked_chat_id=None, location=None, - join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, + can_set_sticker_set=None, linked_chat_id=None, location=None, + join_to_send_messages=None, join_by_request=None, has_restricted_voice_and_video_messages=None, is_forum=None, max_reaction_count=None, active_usernames=None, emoji_status_custom_emoji_id=None, - has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, + has_hidden_members=None, has_aggressive_anti_spam_enabled=None, emoji_status_expiration_date=None, available_reactions=None, accent_color_id=None, background_custom_emoji_id=None, profile_accent_color_id=None, - profile_background_custom_emoji_id=None, has_visible_history=None, + profile_background_custom_emoji_id=None, has_visible_history=None, unrestrict_boost_count=None, custom_emoji_sticker_set_name=None, business_intro=None, business_location=None, - business_opening_hours=None, personal_chat=None, birthdate=None, + business_opening_hours=None, personal_chat=None, birthdate=None, can_send_paid_media=None, accepted_gift_types=None, **kwargs): self.id: int = id @@ -885,7 +885,7 @@ class WebAppData(JsonDeserializable, Dictionaryable): :param data: The data. Be aware that a bad client can send arbitrary data in this field. :type data: :obj:`str` - :param button_text: Text of the web_app keyboard button from which the Web App was opened. Be aware that a bad client + :param button_text: Text of the web_app keyboard button from which the Web App was opened. Be aware that a bad client can send arbitrary data in this field. :type button_text: :obj:`str` @@ -1484,7 +1484,7 @@ def de_json(cls, json_string): if 'direct_message_price_changed' in obj: opts['direct_message_price_changed'] = DirectMessagePriceChanged.de_json(obj['direct_message_price_changed']) content_type = 'direct_message_price_changed' - + return cls(message_id, from_user, date, chat, content_type, opts, json_string) @classmethod @@ -1838,7 +1838,7 @@ class PhotoSize(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -1877,7 +1877,7 @@ class Audio(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -1896,8 +1896,8 @@ class Audio(JsonDeserializable): :param mime_type: Optional. MIME type of the file as defined by sender :type mime_type: :obj:`str` - :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. :type file_size: :obj:`int` @@ -1913,11 +1913,11 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'thumbnail' in obj and 'file_id' in obj['thumbnail']: obj['thumbnail'] = PhotoSize.de_json(obj['thumbnail']) - else: + else: obj['thumbnail'] = None return cls(**obj) - def __init__(self, file_id, file_unique_id, duration, performer=None, title=None, file_name=None, mime_type=None, + def __init__(self, file_id, file_unique_id, duration, performer=None, title=None, file_name=None, mime_type=None, file_size=None, thumbnail=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id @@ -1944,7 +1944,7 @@ class Voice(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -1954,8 +1954,8 @@ class Voice(JsonDeserializable): :param mime_type: Optional. MIME type of the file as defined by sender :type mime_type: :obj:`str` - :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. :type file_size: :obj:`int` @@ -1985,7 +1985,7 @@ class Document(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -1998,8 +1998,8 @@ class Document(JsonDeserializable): :param mime_type: Optional. MIME type of the file as defined by sender :type mime_type: :obj:`str` - :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. :type file_size: :obj:`int` @@ -2012,7 +2012,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'thumbnail' in obj and 'file_id' in obj['thumbnail']: obj['thumbnail'] = PhotoSize.de_json(obj['thumbnail']) - else: + else: obj['thumbnail'] = None return cls(**obj) @@ -2039,7 +2039,7 @@ class Video(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -2067,8 +2067,8 @@ class Video(JsonDeserializable): :param mime_type: Optional. MIME type of the file as defined by sender :type mime_type: :obj:`str` - :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. :type file_size: :obj:`int` @@ -2114,7 +2114,7 @@ class VideoNote(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -2170,8 +2170,8 @@ class Contact(JsonDeserializable): :param last_name: Optional. Contact's last name :type last_name: :obj:`str` - :param user_id: Optional. Contact's user identifier in Telegram. This number may have more than 32 significant bits - and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 + :param user_id: Optional. Contact's user identifier in Telegram. This number may have more than 32 significant bits + and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a 64-bit integer or double-precision float type are safe for storing this identifier. :type user_id: :obj:`int` @@ -2210,14 +2210,14 @@ class Location(JsonDeserializable, JsonSerializable, Dictionaryable): :param horizontal_accuracy: Optional. The radius of uncertainty for the location, measured in meters; 0-1500 :type horizontal_accuracy: :obj:`float` number - :param live_period: Optional. Time relative to the message sending date, during which the location can be updated; + :param live_period: Optional. Time relative to the message sending date, during which the location can be updated; in seconds. For active live locations only. :type live_period: :obj:`int` :param heading: Optional. The direction in which user is moving, in degrees; 1-360. For active live locations only. :type heading: :obj:`int` - :param proximity_alert_radius: Optional. The maximum distance for proximity alerts about approaching another + :param proximity_alert_radius: Optional. The maximum distance for proximity alerts about approaching another chat member, in meters. For sent live locations only. :type proximity_alert_radius: :obj:`int` @@ -2238,10 +2238,10 @@ def __init__(self, longitude, latitude, horizontal_accuracy=None, self.live_period: Optional[int] = live_period self.heading: Optional[int] = heading self.proximity_alert_radius: Optional[int] = proximity_alert_radius - + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): return { "longitude": self.longitude, @@ -2271,7 +2271,7 @@ class Venue(JsonDeserializable): :param foursquare_id: Optional. Foursquare identifier of the venue :type foursquare_id: :obj:`str` - :param foursquare_type: Optional. Foursquare type of the venue. (For example, “arts_entertainment/default”, + :param foursquare_type: Optional. Foursquare type of the venue. (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.) :type foursquare_type: :obj:`str` @@ -2291,7 +2291,7 @@ def de_json(cls, json_string): obj['location'] = Location.de_json(obj['location']) return cls(**obj) - def __init__(self, location, title, address, foursquare_id=None, foursquare_type=None, + def __init__(self, location, title, address, foursquare_id=None, foursquare_type=None, google_place_id=None, google_place_type=None, **kwargs): self.location: Location = location self.title: str = title @@ -2340,16 +2340,16 @@ class File(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` - :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. :type file_size: :obj:`int` - :param file_path: Optional. File path. Use https://api.telegram.org/file/bot/ to get the + :param file_path: Optional. File path. Use https://api.telegram.org/file/bot/ to get the file. :type file_path: :obj:`str` @@ -2376,11 +2376,11 @@ class ForceReply(JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#forcereply - :param force_reply: Shows reply interface to the user, as if they manually selected the bot's message and tapped + :param force_reply: Shows reply interface to the user, as if they manually selected the bot's message and tapped 'Reply' :type force_reply: :obj:`bool` - :param input_field_placeholder: Optional. The placeholder to be shown in the input field when the reply is active; + :param input_field_placeholder: Optional. The placeholder to be shown in the input field when the reply is active; 1-64 characters :type input_field_placeholder: :obj:`str` @@ -2412,16 +2412,16 @@ class ReplyKeyboardRemove(JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#replykeyboardremove - :param remove_keyboard: Requests clients to remove the custom keyboard (user will not be able to summon this - keyboard; if you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in + :param remove_keyboard: Requests clients to remove the custom keyboard (user will not be able to summon this + keyboard; if you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in ReplyKeyboardMarkup) Note that this parameter is set to True by default by the library. You cannot modify it. :type remove_keyboard: :obj:`bool` - :param selective: Optional. Use this parameter if you want to remove the keyboard for specific users only. Targets: - 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply (has - reply_to_message_id), sender of the original message.Example: A user votes in a poll, bot returns confirmation - message in reply to the vote and removes the keyboard for that user, while still showing the keyboard with poll options + :param selective: Optional. Use this parameter if you want to remove the keyboard for specific users only. Targets: + 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply (has + reply_to_message_id), sender of the original message.Example: A user votes in a poll, bot returns confirmation + message in reply to the vote and removes the keyboard for that user, while still showing the keyboard with poll options to users who haven't voted yet. :type selective: :obj:`bool` @@ -2483,21 +2483,21 @@ class ReplyKeyboardMarkup(JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#replykeyboardmarkup - :param keyboard: :obj:`list` of button rows, each represented by an :obj:`list` of + :param keyboard: :obj:`list` of button rows, each represented by an :obj:`list` of :class:`telebot.types.KeyboardButton` objects :type keyboard: :obj:`list` of :obj:`list` of :class:`telebot.types.KeyboardButton` - :param resize_keyboard: Optional. Requests clients to resize the keyboard vertically for optimal fit (e.g., make - the keyboard smaller if there are just two rows of buttons). Defaults to false, in which case the custom keyboard is + :param resize_keyboard: Optional. Requests clients to resize the keyboard vertically for optimal fit (e.g., make + the keyboard smaller if there are just two rows of buttons). Defaults to false, in which case the custom keyboard is always of the same height as the app's standard keyboard. :type resize_keyboard: :obj:`bool` - :param one_time_keyboard: Optional. Requests clients to hide the keyboard as soon as it's been used. The keyboard - will still be available, but clients will automatically display the usual letter-keyboard in the chat - the user can + :param one_time_keyboard: Optional. Requests clients to hide the keyboard as soon as it's been used. The keyboard + will still be available, but clients will automatically display the usual letter-keyboard in the chat - the user can press a special button in the input field to see the custom keyboard again. Defaults to false. :type one_time_keyboard: :obj:`bool` - :param input_field_placeholder: Optional. The placeholder to be shown in the input field when the keyboard is + :param input_field_placeholder: Optional. The placeholder to be shown in the input field when the keyboard is active; 1-64 characters :type input_field_placeholder: :obj:`str` @@ -2511,7 +2511,7 @@ class ReplyKeyboardMarkup(JsonSerializable): :param is_persistent: Optional. Use this parameter if you want to show the keyboard to specific users only. Targets: 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message. - + Example: A user requests to change the bot's language, bot replies to the request with a keyboard to select the new language. Other users in the group don't see the keyboard. @@ -2520,7 +2520,7 @@ class ReplyKeyboardMarkup(JsonSerializable): """ max_row_keys = 12 - def __init__(self, resize_keyboard: Optional[bool]=None, one_time_keyboard: Optional[bool]=None, + def __init__(self, resize_keyboard: Optional[bool]=None, one_time_keyboard: Optional[bool]=None, selective: Optional[bool]=None, row_width: int=3, input_field_placeholder: Optional[str]=None, is_persistent: Optional[bool]=None): if row_width > self.max_row_keys: @@ -2562,7 +2562,7 @@ def add(self, *args, row_width=None) -> 'ReplyKeyboardMarkup': if not DISABLE_KEYLEN_ERROR: logger.error('Telegram does not support reply keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys - + for row in service_utils.chunks(args, row_width): button_array = [] for button in row: @@ -2624,8 +2624,8 @@ def __init__(self, type=None): def to_dict(self): return {'type': self.type} - - + + class KeyboardButtonRequestUsers(Dictionaryable): """ This object defines the criteria used to request a suitable user. @@ -2795,23 +2795,23 @@ class KeyboardButton(Dictionaryable, JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#keyboardbutton - :param text: Text of the button. If none of the optional fields are used, it will be sent as a message when the button is + :param text: Text of the button. If none of the optional fields are used, it will be sent as a message when the button is pressed :type text: :obj:`str` - :param request_contact: Optional. If True, the user's phone number will be sent as a contact when the button is + :param request_contact: Optional. If True, the user's phone number will be sent as a contact when the button is pressed. Available in private chats only. :type request_contact: :obj:`bool` - :param request_location: Optional. If True, the user's current location will be sent when the button is pressed. + :param request_location: Optional. If True, the user's current location will be sent when the button is pressed. Available in private chats only. :type request_location: :obj:`bool` - :param request_poll: Optional. If specified, the user will be asked to create a poll and send it to the bot when the + :param request_poll: Optional. If specified, the user will be asked to create a poll and send it to the bot when the button is pressed. Available in private chats only. :type request_poll: :class:`telebot.types.KeyboardButtonPollType` - :param web_app: Optional. If specified, the described Web App will be launched when the button is pressed. The Web App + :param web_app: Optional. If specified, the described Web App will be launched when the button is pressed. The Web App will be able to send a “web_app_data” service message. Available in private chats only. :type web_app: :class:`telebot.types.WebAppInfo` @@ -2829,7 +2829,7 @@ class KeyboardButton(Dictionaryable, JsonSerializable): :return: Instance of the class :rtype: :class:`telebot.types.KeyboardButton` """ - def __init__(self, text: str, request_contact: Optional[bool]=None, + def __init__(self, text: str, request_contact: Optional[bool]=None, request_location: Optional[bool]=None, request_poll: Optional[KeyboardButtonPollType]=None, web_app: Optional[WebAppInfo]=None, request_user: Optional[KeyboardButtonRequestUser]=None, request_chat: Optional[KeyboardButtonRequestChat]=None, request_users: Optional[KeyboardButtonRequestUsers]=None): @@ -2889,7 +2889,7 @@ class InlineKeyboardMarkup(Dictionaryable, JsonSerializable, JsonDeserializable) Telegram Documentation: https://core.telegram.org/bots/api#inlinekeyboardmarkup - :param keyboard: :obj:`list` of button rows, each represented by an :obj:`list` of + :param keyboard: :obj:`list` of button rows, each represented by an :obj:`list` of :class:`telebot.types.InlineKeyboardButton` objects :type keyboard: :obj:`list` of :obj:`list` of :class:`telebot.types.InlineKeyboardButton` @@ -2900,7 +2900,7 @@ class InlineKeyboardMarkup(Dictionaryable, JsonSerializable, JsonDeserializable) :rtype: :class:`telebot.types.InlineKeyboardMarkup` """ max_row_keys = 8 - + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -2913,7 +2913,7 @@ def __init__(self, keyboard=None, row_width=3): # Todo: Will be replaced with Exception in future releases logger.error('Telegram does not support inline keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys - + self.row_width: int = row_width self.keyboard: List[List[InlineKeyboardButton]] = keyboard or [] @@ -2927,7 +2927,7 @@ def add(self, *args, row_width=None) -> 'InlineKeyboardMarkup': When row_width is set to 2, the result: {keyboard: [["A", "B"], ["C"]]} See https://core.telegram.org/bots/api#inlinekeyboardmarkup - + :param args: Array of InlineKeyboardButton to append to the keyboard :type args: :obj:`list` of :class:`telebot.types.InlineKeyboardButton` @@ -2939,18 +2939,18 @@ def add(self, *args, row_width=None) -> 'InlineKeyboardMarkup': """ if row_width is None: row_width = self.row_width - + if row_width > self.max_row_keys: # Todo: Will be replaced with Exception in future releases logger.error('Telegram does not support inline keyboard row width over %d.' % self.max_row_keys) row_width = self.max_row_keys - + for row in service_utils.chunks(args, row_width): button_array = [button for button in row] self.keyboard.append(button_array) - + return self - + def row(self, *args) -> 'InlineKeyboardMarkup': """ Adds a list of InlineKeyboardButton to the keyboard. @@ -2959,14 +2959,14 @@ def row(self, *args) -> 'InlineKeyboardMarkup': InlineKeyboardMarkup.row("A").row("B", "C").to_json() outputs: '{keyboard: [["A"], ["B", "C"]]}' See https://core.telegram.org/bots/api#inlinekeyboardmarkup - + :param args: Array of InlineKeyboardButton to append to the keyboard :type args: :obj:`list` of :class:`telebot.types.InlineKeyboardButton` :return: self, to allow function chaining. :rtype: :class:`telebot.types.InlineKeyboardMarkup` """ - + return self.add(*args, row_width=self.max_row_keys) def to_json(self): @@ -2987,32 +2987,32 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable) :param text: Label text on the button :type text: :obj:`str` - :param url: Optional. HTTP or tg:// URL to be opened when the button is pressed. Links tg://user?id= can be + :param url: Optional. HTTP or tg:// URL to be opened when the button is pressed. Links tg://user?id= can be used to mention a user by their ID without using a username, if this is allowed by their privacy settings. :type url: :obj:`str` :param callback_data: Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes :type callback_data: :obj:`str` - :param web_app: Optional. Description of the Web App that will be launched when the user presses the button. The Web - App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Available only + :param web_app: Optional. Description of the Web App that will be launched when the user presses the button. The Web + App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Available only in private chats between a user and the bot. :type web_app: :class:`telebot.types.WebAppInfo` - :param login_url: Optional. An HTTPS URL used to automatically authorize the user. Can be used as a replacement for + :param login_url: Optional. An HTTPS URL used to automatically authorize the user. Can be used as a replacement for the Telegram Login Widget. :type login_url: :class:`telebot.types.LoginUrl` - :param switch_inline_query: Optional. If set, pressing the button will prompt the user to select one of their chats, - open that chat and insert the bot's username and the specified inline query in the input field. May be empty, in which - case just the bot's username will be inserted.Note: This offers an easy way for users to start using your bot in inline - mode when they are currently in a private chat with it. Especially useful when combined with switch_pm… actions - in + :param switch_inline_query: Optional. If set, pressing the button will prompt the user to select one of their chats, + open that chat and insert the bot's username and the specified inline query in the input field. May be empty, in which + case just the bot's username will be inserted.Note: This offers an easy way for users to start using your bot in inline + mode when they are currently in a private chat with it. Especially useful when combined with switch_pm… actions - in this case the user will be automatically returned to the chat they switched from, skipping the chat selection screen. :type switch_inline_query: :obj:`str` - :param switch_inline_query_current_chat: Optional. If set, pressing the button will insert the bot's username - and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username - will be inserted.This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting + :param switch_inline_query_current_chat: Optional. If set, pressing the button will insert the bot's username + and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username + will be inserted.This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. :type switch_inline_query_current_chat: :obj:`str` @@ -3020,11 +3020,11 @@ class InlineKeyboardButton(Dictionaryable, JsonSerializable, JsonDeserializable) specified type, open that chat and insert the bot's username and the specified inline query in the input field :type switch_inline_query_chosen_chat: :class:`telebot.types.SwitchInlineQueryChosenChat` - :param callback_game: Optional. Description of the game that will be launched when the user presses the + :param callback_game: Optional. Description of the game that will be launched when the user presses the button. NOTE: This type of button must always be the first button in the first row. :type callback_game: :class:`telebot.types.CallbackGame` - :param pay: Optional. Specify True, to send a Pay button. NOTE: This type of button must always be the first button in + :param pay: Optional. Specify True, to send a Pay button. NOTE: This type of button must always be the first button in the first row and can only be used in invoice messages. :type pay: :obj:`bool` @@ -3046,7 +3046,7 @@ def de_json(cls, json_string): obj['switch_inline_query_chosen_chat'] = SwitchInlineQueryChosenChat.de_json(obj.get('switch_inline_query_chosen_chat')) if 'copy_text' in obj: obj['copy_text'] = CopyTextButton.de_json(obj.get('copy_text')) - + return cls(**obj) def __init__(self, text: str, url: Optional[str]=None, callback_data: Optional[str]=None, web_app: Optional[WebAppInfo]=None, @@ -3099,22 +3099,22 @@ class LoginUrl(Dictionaryable, JsonSerializable, JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#loginurl - :param url: An HTTPS URL to be opened with user authorization data added to the query string when the button is pressed. - If the user refuses to provide authorization data, the original URL without information about the user will be - opened. The data added is the same as described in Receiving authorization data. NOTE: You must always check the hash - of the received data to verify the authentication and the integrity of the data as described in Checking + :param url: An HTTPS URL to be opened with user authorization data added to the query string when the button is pressed. + If the user refuses to provide authorization data, the original URL without information about the user will be + opened. The data added is the same as described in Receiving authorization data. NOTE: You must always check the hash + of the received data to verify the authentication and the integrity of the data as described in Checking authorization. :type url: :obj:`str` :param forward_text: Optional. New text of the button in forwarded messages. :type forward_text: :obj:`str` - :param bot_username: Optional. Username of a bot, which will be used for user authorization. See Setting up a bot for - more details. If not specified, the current bot's username will be assumed. The url's domain must be the same as the + :param bot_username: Optional. Username of a bot, which will be used for user authorization. See Setting up a bot for + more details. If not specified, the current bot's username will be assumed. The url's domain must be the same as the domain linked with the bot. See Linking your domain to the bot for more details. :type bot_username: :obj:`str` - :param request_write_access: Optional. Pass True to request the permission for your bot to send messages to the + :param request_write_access: Optional. Pass True to request the permission for your bot to send messages to the user. :type request_write_access: :obj:`bool` @@ -3164,15 +3164,15 @@ class CallbackQuery(JsonDeserializable): :param message: Optional. Message sent by the bot with the callback button that originated the query :type message: :class:`telebot.types.Message` or :class:`telebot.types.InaccessibleMessage` - :param inline_message_id: Optional. Identifier of the message sent via the bot in inline mode, that originated the + :param inline_message_id: Optional. Identifier of the message sent via the bot in inline mode, that originated the query. :type inline_message_id: :obj:`str` - :param chat_instance: Global identifier, uniquely corresponding to the chat to which the message with the callback + :param chat_instance: Global identifier, uniquely corresponding to the chat to which the message with the callback button was sent. Useful for high scores in games. :type chat_instance: :obj:`str` - :param data: Optional. Data associated with the callback button. Be aware that the message originated the query can + :param data: Optional. Data associated with the callback button. Be aware that the message originated the query can contain no callback buttons with this data. :type data: :obj:`str` @@ -3211,27 +3211,27 @@ def __init__( self.data: Optional[str] = data self.game_short_name: Optional[str] = game_short_name self.json = json_string - - + + class ChatPhoto(JsonDeserializable): """ This object represents a chat photo. Telegram Documentation: https://core.telegram.org/bots/api#chatphoto - :param small_file_id: File identifier of small (160x160) chat photo. This file_id can be used only for photo + :param small_file_id: File identifier of small (160x160) chat photo. This file_id can be used only for photo download and only for as long as the photo is not changed. :type small_file_id: :obj:`str` - :param small_file_unique_id: Unique file identifier of small (160x160) chat photo, which is supposed to be the same + :param small_file_unique_id: Unique file identifier of small (160x160) chat photo, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type small_file_unique_id: :obj:`str` - :param big_file_id: File identifier of big (640x640) chat photo. This file_id can be used only for photo download and + :param big_file_id: File identifier of big (640x640) chat photo. This file_id can be used only for photo download and only for as long as the photo is not changed. :type big_file_id: :obj:`str` - :param big_file_unique_id: Unique file identifier of big (640x640) chat photo, which is supposed to be the same over + :param big_file_unique_id: Unique file identifier of big (640x640) chat photo, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type big_file_unique_id: :obj:`str` @@ -3251,11 +3251,11 @@ def __init__(self, small_file_id, small_file_unique_id, big_file_id, big_file_un self.big_file_unique_id: str = big_file_unique_id -class ChatMember(JsonDeserializable): +class ChatMember(JsonDeserializable, ABC): """ This object contains information about one member of a chat. Currently, the following 6 types of chat members are supported: - + * :class:`telebot.types.ChatMemberOwner` * :class:`telebot.types.ChatMemberAdministrator` * :class:`telebot.types.ChatMemberMember` @@ -3266,78 +3266,31 @@ class ChatMember(JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#chatmember """ + def __init__(self, user, status, **kwargs): + self.user: User = user + self.status: str = status + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['user'] = User.de_json(obj['user']) - member_type = obj['status'] + status = obj['status'] # Ordered according to estimated appearance frequency. - if member_type == "member": + if status == "member": return ChatMemberMember(**obj) - elif member_type == "left": + elif status == "left": return ChatMemberLeft(**obj) - elif member_type == "kicked": + elif status == "kicked": return ChatMemberBanned(**obj) - elif member_type == "restricted": + elif status == "restricted": return ChatMemberRestricted(**obj) - elif member_type == "administrator": + elif status == "administrator": return ChatMemberAdministrator(**obj) - elif member_type == "creator": + elif status == "creator": return ChatMemberOwner(**obj) else: - # Should not be here. For "if something happen" compatibility - return cls(**obj) - - def __init__(self, user, status, custom_title=None, is_anonymous=None, can_be_edited=None, - can_post_messages=None, can_edit_messages=None, can_delete_messages=None, - can_restrict_members=None, can_promote_members=None, can_change_info=None, - can_invite_users=None, can_pin_messages=None, is_member=None, - can_send_messages=None, can_send_audios=None, can_send_documents=None, - can_send_photos=None, can_send_videos=None, can_send_video_notes=None, - can_send_voice_notes=None, - can_send_polls=None, - can_send_other_messages=None, can_add_web_page_previews=None, - can_manage_chat=None, can_manage_video_chats=None, - until_date=None, can_manage_topics=None, - can_post_stories=None, can_edit_stories=None, can_delete_stories=None, - **kwargs): - self.user: User = user - self.status: str = status - self.custom_title: str = custom_title - self.is_anonymous: bool = is_anonymous - self.can_be_edited: bool = can_be_edited - self.can_post_messages: bool = can_post_messages - self.can_edit_messages: bool = can_edit_messages - self.can_delete_messages: bool = can_delete_messages - self.can_restrict_members: bool = can_restrict_members - self.can_promote_members: bool = can_promote_members - self.can_change_info: bool = can_change_info - self.can_invite_users: bool = can_invite_users - self.can_pin_messages: bool = can_pin_messages - self.is_member: bool = is_member - self.can_send_messages: bool = can_send_messages - self.can_send_polls: bool = can_send_polls - self.can_send_other_messages: bool = can_send_other_messages - self.can_add_web_page_previews: bool = can_add_web_page_previews - self.can_manage_chat: bool = can_manage_chat - self.can_manage_video_chats: bool = can_manage_video_chats - self.until_date: int = until_date - self.can_manage_topics: bool = can_manage_topics - self.can_send_audios: bool = can_send_audios - self.can_send_documents: bool = can_send_documents - self.can_send_photos: bool = can_send_photos - self.can_send_videos: bool = can_send_videos - self.can_send_video_notes: bool = can_send_video_notes - self.can_send_voice_notes: bool = can_send_voice_notes - self.can_post_stories: bool = can_post_stories - self.can_edit_stories: bool = can_edit_stories - self.can_delete_stories: bool = can_delete_stories - - @property - def can_manage_voice_chats(self): - log_deprecation_warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') - return self.can_manage_video_chats + raise ValueError(f"Unknown chat member type: {status}.") # noinspection PyUnresolvedReferences @@ -3362,7 +3315,10 @@ class ChatMemberOwner(ChatMember): :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberOwner` """ - pass + def __init__(self, user, status, is_anonymous, custom_title=None, **kwargs): + super().__init__(user, status, **kwargs) + self.is_anonymous: bool = is_anonymous + self.custom_title: Optional[str] = custom_title # noinspection PyUnresolvedReferences @@ -3384,8 +3340,8 @@ class ChatMemberAdministrator(ChatMember): :param is_anonymous: True, if the user's presence in the chat is hidden :type is_anonymous: :obj:`bool` - :param can_manage_chat: True, if the administrator can access the chat event log, chat statistics, message - statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. + :param can_manage_chat: True, if the administrator can access the chat event log, chat statistics, message + statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege :type can_manage_chat: :obj:`bool` @@ -3398,8 +3354,8 @@ class ChatMemberAdministrator(ChatMember): :param can_restrict_members: True, if the administrator can restrict, ban or unban chat members :type can_restrict_members: :obj:`bool` - :param can_promote_members: True, if the administrator can add new administrators with a subset of their own - privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that + :param can_promote_members: True, if the administrator can add new administrators with a subset of their own + privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by the user) :type can_promote_members: :obj:`bool` @@ -3409,36 +3365,60 @@ class ChatMemberAdministrator(ChatMember): :param can_invite_users: True, if the user is allowed to invite new users to the chat :type can_invite_users: :obj:`bool` + :param can_post_stories: True, if the administrator can post channel stories + :type can_post_stories: :obj:`bool` + + :param can_edit_stories: True, if the administrator can edit stories + :type can_edit_stories: :obj:`bool` + + :param can_delete_stories: True, if the administrator can delete stories of other users + :type can_delete_stories: :obj:`bool` + :param can_post_messages: Optional. True, if the administrator can post in the channel; channels only :type can_post_messages: :obj:`bool` - :param can_edit_messages: Optional. True, if the administrator can edit messages of other users and can pin - messages; channels only + :param can_edit_messages: Optional. True, if the administrator can edit messages of other users and can pin messages; channels only :type can_edit_messages: :obj:`bool` :param can_pin_messages: Optional. True, if the user is allowed to pin messages; groups and supergroups only :type can_pin_messages: :obj:`bool` - :param can_manage_topics: Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; - supergroups only + :param can_manage_topics: Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only :type can_manage_topics: :obj:`bool` :param custom_title: Optional. Custom title for this user :type custom_title: :obj:`str` - :param can_post_stories: Optional. True, if the administrator can post channel stories - :type can_post_stories: :obj:`bool` - - :param can_edit_stories: Optional. True, if the administrator can edit stories - :type can_edit_stories: :obj:`bool` - - :param can_delete_stories: Optional. True, if the administrator can delete stories of other users - :type can_delete_stories: :obj:`bool` - :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberAdministrator` """ - pass + def __init__(self, user, status, can_be_edited, is_anonymous, can_manage_chat, can_delete_messages, + can_manage_video_chats, can_restrict_members, can_promote_members, can_change_info, can_invite_users, + can_post_stories, can_edit_stories, can_delete_stories, can_post_messages=None, can_edit_messages=None, + can_pin_messages=None, can_manage_topics=None, custom_title=None, **kwargs): + super().__init__(user, status, **kwargs) + self.can_be_edited: bool = can_be_edited + self.is_anonymous: bool = is_anonymous + self.can_manage_chat: bool = can_manage_chat + self.can_delete_messages: bool = can_delete_messages + self.can_manage_video_chats: bool = can_manage_video_chats + self.can_restrict_members: bool = can_restrict_members + self.can_promote_members: bool = can_promote_members + self.can_change_info: bool = can_change_info + self.can_invite_users: bool = can_invite_users + self.can_post_stories: bool = can_post_stories + self.can_edit_stories: bool = can_edit_stories + self.can_delete_stories: bool = can_delete_stories + self.can_post_messages: Optional[bool] = can_post_messages + self.can_edit_messages: Optional[bool] = can_edit_messages + self.can_pin_messages: Optional[bool] = can_pin_messages + self.can_manage_topics: Optional[bool] = can_manage_topics + self.custom_title: Optional[str] = custom_title + + @property + def can_manage_voice_chats(self): + log_deprecation_warning('The parameter "can_manage_voice_chats" is deprecated. Use "can_manage_video_chats" instead.') + return self.can_manage_video_chats # noinspection PyUnresolvedReferences @@ -3454,10 +3434,15 @@ class ChatMemberMember(ChatMember): :param user: Information about the user :type user: :class:`telebot.types.User` + :param until_date: Optional. Date when the user's subscription will expire; Unix time. If 0, then the user is a member forever + :type until_date: :obj:`int` + :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberMember` """ - pass + def __init__(self, user, status, until_date=None, **kwargs): + super().__init__(user, status, **kwargs) + self.until_date: Optional[int] = until_date # noinspection PyUnresolvedReferences @@ -3476,18 +3461,6 @@ class ChatMemberRestricted(ChatMember): :param is_member: True, if the user is a member of the chat at the moment of the request :type is_member: :obj:`bool` - :param can_change_info: True, if the user is allowed to change the chat title, photo and other settings - :type can_change_info: :obj:`bool` - - :param can_invite_users: True, if the user is allowed to invite new users to the chat - :type can_invite_users: :obj:`bool` - - :param can_pin_messages: True, if the user is allowed to pin messages - :type can_pin_messages: :obj:`bool` - - :param can_manage_topics: True, if the user is allowed to create forum topics - :type can_manage_topics: :obj:`bool` - :param can_send_messages: True, if the user is allowed to send text messages, contacts, locations and venues :type can_send_messages: :obj:`bool` @@ -3512,21 +3485,52 @@ class ChatMemberRestricted(ChatMember): :param can_send_polls: True, if the user is allowed to send polls :type can_send_polls: :obj:`bool` - :param can_send_other_messages: True, if the user is allowed to send animations, games, stickers and use inline - bots + :param can_send_other_messages: True, if the user is allowed to send animations, games, stickers and use inline bots :type can_send_other_messages: :obj:`bool` :param can_add_web_page_previews: True, if the user is allowed to add web page previews to their messages :type can_add_web_page_previews: :obj:`bool` - :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted - forever + :param can_change_info: True, if the user is allowed to change the chat title, photo and other settings + :type can_change_info: :obj:`bool` + + :param can_invite_users: True, if the user is allowed to invite new users to the chat + :type can_invite_users: :obj:`bool` + + :param can_pin_messages: True, if the user is allowed to pin messages + :type can_pin_messages: :obj:`bool` + + :param can_manage_topics: True, if the user is allowed to create forum topics + :type can_manage_topics: :obj:`bool` + + :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted forever :type until_date: :obj:`int` :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberRestricted` """ - pass + def __init__(self, user, status, is_member, can_send_messages, can_send_audios, can_send_documents, + can_send_photos, can_send_videos, can_send_video_notes, can_send_voice_notes, can_send_polls, + can_send_other_messages, can_add_web_page_previews, + can_change_info, can_invite_users, can_pin_messages, can_manage_topics, + until_date=None, **kwargs): + super().__init__(user, status, **kwargs) + self.is_member: bool = is_member + self.can_send_messages: bool = can_send_messages + self.can_send_audios: bool = can_send_audios + self.can_send_documents: bool = can_send_documents + self.can_send_photos: bool = can_send_photos + self.can_send_videos: bool = can_send_videos + self.can_send_video_notes: bool = can_send_video_notes + self.can_send_voice_notes: bool = can_send_voice_notes + self.can_send_polls: bool = can_send_polls + self.can_send_other_messages: bool = can_send_other_messages + self.can_add_web_page_previews: bool = can_add_web_page_previews + self.can_change_info: bool = can_change_info + self.can_invite_users: bool = can_invite_users + self.can_pin_messages: bool = can_pin_messages + self.can_manage_topics: bool = can_manage_topics + self.until_date: Optional[int] = until_date # noinspection PyUnresolvedReferences @@ -3561,14 +3565,15 @@ class ChatMemberBanned(ChatMember): :param user: Information about the user :type user: :class:`telebot.types.User` - :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is banned - forever + :param until_date: Date when restrictions will be lifted for this user; unix time. If 0, then the user is banned forever :type until_date: :obj:`int` :return: Instance of the class :rtype: :class:`telebot.types.ChatMemberBanned` """ - pass + def __init__(self, user, status, until_date=None, **kwargs): + super().__init__(user, status, **kwargs) + self.until_date: Optional[int] = until_date class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): @@ -3577,8 +3582,7 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): Telegram Documentation: https://core.telegram.org/bots/api#chatpermissions - :param can_send_messages: Optional. True, if the user is allowed to send text messages, contacts, locations and - venues + :param can_send_messages: Optional. True, if the user is allowed to send text messages, contacts, locations and venues :type can_send_messages: :obj:`bool` :param can_send_audios: Optional. True, if the user is allowed to send audios @@ -3602,15 +3606,15 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): :param can_send_polls: Optional. True, if the user is allowed to send polls, implies can_send_messages :type can_send_polls: :obj:`bool` - :param can_send_other_messages: Optional. True, if the user is allowed to send animations, games, stickers and use + :param can_send_other_messages: Optional. True, if the user is allowed to send animations, games, stickers and use inline bots :type can_send_other_messages: :obj:`bool` - :param can_add_web_page_previews: Optional. True, if the user is allowed to add web page previews to their + :param can_add_web_page_previews: Optional. True, if the user is allowed to add web page previews to their messages :type can_add_web_page_previews: :obj:`bool` - :param can_change_info: Optional. True, if the user is allowed to change the chat title, photo and other settings. + :param can_change_info: Optional. True, if the user is allowed to change the chat title, photo and other settings. Ignored in public supergroups :type can_change_info: :obj:`bool` @@ -3622,7 +3626,7 @@ class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): :param can_manage_topics: Optional. True, if the user is allowed to create forum topics. If omitted defaults to the value of can_pin_messages - :type can_manage_topics: :obj:`bool` + :type can_manage_topics: :obj:`bool` :param can_send_media_messages: deprecated. :type can_send_media_messages: :obj:`bool` @@ -3641,7 +3645,7 @@ def __init__(self, can_send_messages=None, can_send_media_messages=None,can_send can_send_videos=None, can_send_video_notes=None, can_send_voice_notes=None, can_send_polls=None, can_send_other_messages=None, can_add_web_page_previews=None, can_change_info=None, - can_invite_users=None, can_pin_messages=None, + can_invite_users=None, can_pin_messages=None, can_manage_topics=None, **kwargs): self.can_send_messages: Optional[bool] = can_send_messages self.can_send_polls: Optional[bool] = can_send_polls @@ -3704,7 +3708,7 @@ def to_dict(self): json_dict['can_pin_messages'] = self.can_pin_messages if self.can_manage_topics is not None: json_dict['can_manage_topics'] = self.can_manage_topics - + return json_dict @@ -3714,7 +3718,7 @@ class BotCommand(JsonSerializable, JsonDeserializable, Dictionaryable): Telegram Documentation: https://core.telegram.org/bots/api#botcommand - :param command: Text of the command; 1-32 characters. Can contain only lowercase English letters, digits and + :param command: Text of the command; 1-32 characters. Can contain only lowercase English letters, digits and underscores. :type command: :obj:`str` @@ -3891,7 +3895,7 @@ class BotCommandScopeChat(BotCommandScope): :param type: Scope type, must be chat :type type: :obj:`str` - :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format + :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) :type chat_id: :obj:`int` or :obj:`str` @@ -3912,7 +3916,7 @@ class BotCommandScopeChatAdministrators(BotCommandScope): :param type: Scope type, must be chat_administrators :type type: :obj:`str` - :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format + :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) :type chat_id: :obj:`int` or :obj:`str` @@ -3933,7 +3937,7 @@ class BotCommandScopeChatMember(BotCommandScope): :param type: Scope type, must be chat_member :type type: :obj:`str` - :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format + :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) :type chat_id: :obj:`int` or :obj:`str` @@ -3968,9 +3972,9 @@ class InlineQuery(JsonDeserializable): :param offset: Offset of the results to be returned, can be controlled by the bot :type offset: :obj:`str` - :param chat_type: Optional. Type of the chat from which the inline query was sent. Can be either “sender” for a private - chat with the inline query sender, “private”, “group”, “supergroup”, or “channel”. The chat type should be always - known for requests sent from official clients and most third-party clients, unless the request was sent from a secret + :param chat_type: Optional. Type of the chat from which the inline query was sent. Can be either “sender” for a private + chat with the inline query sender, “private”, “group”, “supergroup”, or “channel”. The chat type should be always + known for requests sent from official clients and most third-party clients, unless the request was sent from a secret chat :type chat_type: :obj:`str` @@ -4007,11 +4011,11 @@ class InputTextMessageContent(Dictionaryable): :param message_text: Text of the message to be sent, 1-4096 characters :type message_text: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the message text. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the message text. See formatting options for more details. :type parse_mode: :obj:`str` - :param entities: Optional. List of special entities that appear in message text, which can be specified instead of + :param entities: Optional. List of special entities that appear in message text, which can be specified instead of parse_mode :type entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -4118,7 +4122,7 @@ class InputVenueMessageContent(Dictionaryable): :param foursquare_id: Optional. Foursquare identifier of the venue, if known :type foursquare_id: :obj:`str` - :param foursquare_type: Optional. Foursquare type of the venue, if known. (For example, + :param foursquare_type: Optional. Foursquare type of the venue, if known. (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.) :type foursquare_type: :obj:`str` @@ -4131,7 +4135,7 @@ class InputVenueMessageContent(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.InputVenueMessageContent` """ - def __init__(self, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, + def __init__(self, latitude, longitude, title, address, foursquare_id=None, foursquare_type=None, google_place_id=None, google_place_type=None): self.latitude: float = latitude self.longitude: float = longitude @@ -4208,7 +4212,7 @@ class InputInvoiceMessageContent(Dictionaryable): :param description: Product description, 1-255 characters :type description: :obj:`str` - :param payload: Bot-defined invoice payload, 1-128 bytes. This will not be displayed to the user, use for your + :param payload: Bot-defined invoice payload, 1-128 bytes. This will not be displayed to the user, use for your internal processes. :type payload: :obj:`str` @@ -4219,26 +4223,26 @@ class InputInvoiceMessageContent(Dictionaryable): :param currency: Three-letter ISO 4217 currency code, see more on currencies :type currency: :obj:`str` - :param prices: Price breakdown, a JSON-serialized list of components (e.g. product price, tax, discount, delivery + :param prices: Price breakdown, a JSON-serialized list of components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus, etc.) :type prices: :obj:`list` of :class:`telebot.types.LabeledPrice` - :param max_tip_amount: Optional. The maximum accepted amount for tips in the smallest units of the currency - (integer, not float/double). For example, for a maximum tip of US$ 1.45 pass max_tip_amount = 145. See the exp - parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the + :param max_tip_amount: Optional. The maximum accepted amount for tips in the smallest units of the currency + (integer, not float/double). For example, for a maximum tip of US$ 1.45 pass max_tip_amount = 145. See the exp + parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). Defaults to 0 :type max_tip_amount: :obj:`int` - :param suggested_tip_amounts: Optional. A JSON-serialized array of suggested amounts of tip in the smallest units - of the currency (integer, not float/double). At most 4 suggested tip amounts can be specified. The suggested tip + :param suggested_tip_amounts: Optional. A JSON-serialized array of suggested amounts of tip in the smallest units + of the currency (integer, not float/double). At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount. :type suggested_tip_amounts: :obj:`list` of :obj:`int` - :param provider_data: Optional. A JSON-serialized object for data about the invoice, which will be shared with the + :param provider_data: Optional. A JSON-serialized object for data about the invoice, which will be shared with the payment provider. A detailed description of the required fields should be provided by the payment provider. :type provider_data: :obj:`str` - :param photo_url: Optional. URL of the product photo for the invoice. Can be a photo of the goods or a marketing image + :param photo_url: Optional. URL of the product photo for the invoice. Can be a photo of the goods or a marketing image for a service. :type photo_url: :obj:`str` @@ -4260,7 +4264,7 @@ class InputInvoiceMessageContent(Dictionaryable): :param need_email: Optional. Pass True, if you require the user's email address to complete the order :type need_email: :obj:`bool` - :param need_shipping_address: Optional. Pass True, if you require the user's shipping address to complete the + :param need_shipping_address: Optional. Pass True, if you require the user's shipping address to complete the order :type need_shipping_address: :obj:`bool` @@ -4276,7 +4280,7 @@ class InputInvoiceMessageContent(Dictionaryable): :return: Instance of the class :rtype: :class:`telebot.types.InputInvoiceMessageContent` """ - + def __init__(self, title: str, description: str, payload: str, provider_token: Optional[str], currency: str, prices: List[LabeledPrice], max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]] = None, provider_data: Optional[str] = None, photo_url: Optional[str] = None, photo_size: Optional[int] = None, photo_width: Optional[int] = None, photo_height: Optional[int] = None, @@ -4302,10 +4306,10 @@ def __init__(self, title: str, description: str, payload: str, provider_token: O self.send_phone_number_to_provider: Optional[bool] = send_phone_number_to_provider self.send_email_to_provider: Optional[bool] = send_email_to_provider self.is_flexible: Optional[bool] = is_flexible - + def to_dict(self): json_dict = { - 'title': self.title, + 'title': self.title, 'description': self.description, 'payload': self.payload, 'provider_token': self.provider_token, @@ -4313,33 +4317,33 @@ def to_dict(self): 'prices': [LabeledPrice.to_dict(lp) for lp in self.prices] } if self.max_tip_amount: - json_dict['max_tip_amount'] = self.max_tip_amount + json_dict['max_tip_amount'] = self.max_tip_amount if self.suggested_tip_amounts: - json_dict['suggested_tip_amounts'] = self.suggested_tip_amounts + json_dict['suggested_tip_amounts'] = self.suggested_tip_amounts if self.provider_data: - json_dict['provider_data'] = self.provider_data + json_dict['provider_data'] = self.provider_data if self.photo_url: - json_dict['photo_url'] = self.photo_url + json_dict['photo_url'] = self.photo_url if self.photo_size: - json_dict['photo_size'] = self.photo_size + json_dict['photo_size'] = self.photo_size if self.photo_width: - json_dict['photo_width'] = self.photo_width + json_dict['photo_width'] = self.photo_width if self.photo_height: - json_dict['photo_height'] = self.photo_height + json_dict['photo_height'] = self.photo_height if self.need_name is not None: - json_dict['need_name'] = self.need_name + json_dict['need_name'] = self.need_name if self.need_phone_number is not None: - json_dict['need_phone_number'] = self.need_phone_number + json_dict['need_phone_number'] = self.need_phone_number if self.need_email is not None: - json_dict['need_email'] = self.need_email + json_dict['need_email'] = self.need_email if self.need_shipping_address is not None: - json_dict['need_shipping_address'] = self.need_shipping_address + json_dict['need_shipping_address'] = self.need_shipping_address if self.send_phone_number_to_provider is not None: - json_dict['send_phone_number_to_provider'] = self.send_phone_number_to_provider + json_dict['send_phone_number_to_provider'] = self.send_phone_number_to_provider if self.send_email_to_provider is not None: - json_dict['send_email_to_provider'] = self.send_email_to_provider + json_dict['send_email_to_provider'] = self.send_email_to_provider if self.is_flexible is not None: - json_dict['is_flexible'] = self.is_flexible + json_dict['is_flexible'] = self.is_flexible return json_dict InputMessageContent = Union[InputTextMessageContent, InputLocationMessageContent, InputVenueMessageContent, InputContactMessageContent, InputInvoiceMessageContent] @@ -4359,7 +4363,7 @@ class ChosenInlineResult(JsonDeserializable): :param location: Optional. Sender location, only for bots that require user location :type location: :class:`telebot.types.Location` - :param inline_message_id: Optional. Identifier of the sent inline message. Available only if there is an inline + :param inline_message_id: Optional. Identifier of the sent inline message. Available only if there is an inline keyboard attached to the message. Will be also received in callback queries and can be used to edit the message. :type inline_message_id: :obj:`str` @@ -4414,7 +4418,7 @@ class InlineQueryResultBase(ABC, Dictionaryable, JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#inlinequeryresult """ - + def __init__(self, type: str, id: str, title: Optional[str] = None, caption: Optional[str] = None, input_message_content: Optional[InputMessageContent] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None): self.type: str = type @@ -4455,7 +4459,7 @@ class SentWebAppMessage(JsonDeserializable, Dictionaryable): Telegram Documentation: https://core.telegram.org/bots/api#sentwebappmessage - :param inline_message_id: Optional. Identifier of the sent inline message. Available only if there is an inline + :param inline_message_id: Optional. Identifier of the sent inline message. Available only if there is an inline keyboard attached to the message. :type inline_message_id: :obj:`str` @@ -4521,11 +4525,11 @@ class InlineQueryResultArticle(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultArticle` """ - + def __init__(self, id: str, title: str, input_message_content: InputMessageContent, reply_markup: Optional[InlineKeyboardMarkup] = None, url: Optional[str] = None, hide_url: Optional[bool] = None, description: Optional[str] = None, thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None): - + super().__init__('article', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) self.url: Optional[str] = url self.hide_url: Optional[bool] = hide_url @@ -4605,11 +4609,11 @@ class InlineQueryResultPhoto(InlineQueryResultBase): :param caption: Optional. Caption of the photo to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the photo caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the photo caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -4688,7 +4692,7 @@ class InlineQueryResultGif(InlineQueryResultBase): :param thumbnail_url: URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result :type thumbnail_url: :obj:`str` - :param thumbnail_mime_type: Optional. MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or + :param thumbnail_mime_type: Optional. MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or “video/mp4”. Defaults to “image/jpeg” :type thumbnail_mime_type: :obj:`str` @@ -4701,7 +4705,7 @@ class InlineQueryResultGif(InlineQueryResultBase): :param parse_mode: Optional. Mode for parsing entities in the caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -4722,7 +4726,7 @@ def __init__(self, id: str, gif_url: str, thumbnail_url: str, gif_width: Optiona reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, gif_duration: Optional[int] = None, parse_mode: Optional[str] = None, thumbnail_mime_type: Optional[str] = None, show_caption_above_media: Optional[bool] = None): - + super().__init__('gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4789,7 +4793,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResultBase): :param thumbnail_url: URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result :type thumbnail_url: :obj:`str` - :param thumbnail_mime_type: Optional. MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or + :param thumbnail_mime_type: Optional. MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or “video/mp4”. Defaults to “image/jpeg” :type thumbnail_mime_type: :obj:`str` @@ -4802,7 +4806,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResultBase): :param parse_mode: Optional. Mode for parsing entities in the caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -4822,7 +4826,7 @@ def __init__(self, id: str, mpeg4_url: str, thumbnail_url: str, mpeg4_width: Opt title: Optional[str] = None, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, mpeg4_duration: Optional[int] = None, thumbnail_mime_type: Optional[str] = None, show_caption_above_media: Optional[bool] = None): - + super().__init__('mpeg4_gif', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4889,11 +4893,11 @@ class InlineQueryResultVideo(InlineQueryResultBase): :param caption: Optional. Caption of the video to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the video caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the video caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -4912,7 +4916,7 @@ class InlineQueryResultVideo(InlineQueryResultBase): :param reply_markup: Optional. Inline keyboard attached to the message :type reply_markup: :class:`telebot.types.InlineKeyboardMarkup` - :param input_message_content: Optional. Content of the message to be sent instead of the video. This field is + :param input_message_content: Optional. Content of the message to be sent instead of the video. This field is required if InlineQueryResultVideo is used to send an HTML-page as a result (e.g., a YouTube video). :type input_message_content: :class:`telebot.types.InputMessageContent` @@ -4927,7 +4931,7 @@ def __init__(self, id: str, video_url: str, mime_type: str, thumbnail_url: str, parse_mode: Optional[str] = None, video_width: Optional[int] = None, video_height: Optional[int] = None, video_duration: Optional[int] = None, description: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): - + super().__init__('video', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -4983,11 +4987,11 @@ class InlineQueryResultAudio(InlineQueryResultBase): :param caption: Optional. Caption, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the audio caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the audio caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5009,7 +5013,7 @@ class InlineQueryResultAudio(InlineQueryResultBase): def __init__(self, id: str, audio_url: str, title: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, performer: Optional[str] = None, audio_duration: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): - + super().__init__('audio', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -5049,11 +5053,11 @@ class InlineQueryResultVoice(InlineQueryResultBase): :param caption: Optional. Caption, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the voice message caption. See formatting options for + :param parse_mode: Optional. Mode for parsing entities in the voice message caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5072,7 +5076,7 @@ class InlineQueryResultVoice(InlineQueryResultBase): def __init__(self, id: str, voice_url: str, title: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, voice_duration: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): - + super().__init__('voice', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -5106,11 +5110,11 @@ class InlineQueryResultDocument(InlineQueryResultBase): :param caption: Optional. Caption of the document to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the document caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the document caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5145,7 +5149,7 @@ def __init__(self, id: str, title: str, document_url: str, mime_type: str, capti parse_mode: Optional[str] = None, description: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None): - + super().__init__('document', id, title = title, caption = caption, input_message_content = input_message_content, reply_markup = reply_markup, parse_mode = parse_mode, caption_entities = caption_entities) @@ -5243,7 +5247,7 @@ def __init__(self, id: str, title: str, latitude: float, longitude: float, horiz reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None, heading: Optional[int] = None, proximity_alert_radius: Optional[int] = None): - + super().__init__('location', id, title = title, input_message_content = input_message_content, reply_markup = reply_markup) self.latitude: float = latitude @@ -5320,7 +5324,7 @@ class InlineQueryResultVenue(InlineQueryResultBase): :param foursquare_id: Optional. Foursquare identifier of the venue if known :type foursquare_id: :obj:`str` - :param foursquare_type: Optional. Foursquare type of the venue, if known. (For example, + :param foursquare_type: Optional. Foursquare type of the venue, if known. (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.) :type foursquare_type: :obj:`str` @@ -5446,7 +5450,7 @@ class InlineQueryResultContact(InlineQueryResultBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultContact` """ - + def __init__(self, id: str, phone_number: str, first_name: str, last_name: Optional[str] = None, vcard: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, thumbnail_url: Optional[str] = None, thumbnail_width: Optional[int] = None, thumbnail_height: Optional[int] = None): @@ -5591,11 +5595,11 @@ class InlineQueryResultCachedPhoto(InlineQueryResultCachedBase): :param caption: Optional. Caption of the photo to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the photo caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the photo caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5657,7 +5661,7 @@ class InlineQueryResultCachedGif(InlineQueryResultCachedBase): :param parse_mode: Optional. Mode for parsing entities in the caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5677,7 +5681,7 @@ def __init__(self, id: str, gif_file_id: str, title: Optional[str] = None, descr caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): - + InlineQueryResultCachedBase.__init__(self) self.type: str = 'gif' self.id: str = id @@ -5718,7 +5722,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResultCachedBase): :param parse_mode: Optional. Mode for parsing entities in the caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5738,7 +5742,7 @@ def __init__(self, id: str, mpeg4_file_id: str, title: Optional[str] = None, des caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): - + InlineQueryResultCachedBase.__init__(self) self.type: str = 'mpeg4_gif' self.id: str = id @@ -5815,11 +5819,11 @@ class InlineQueryResultCachedDocument(InlineQueryResultCachedBase): :param caption: Optional. Caption of the document to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the document caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the document caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5837,7 +5841,7 @@ def __init__(self, id: str, document_file_id: str, title: str, description: Opti caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): - + InlineQueryResultCachedBase.__init__(self) self.type: str = 'document' self.id: str = id @@ -5877,11 +5881,11 @@ class InlineQueryResultCachedVideo(InlineQueryResultCachedBase): :param caption: Optional. Caption of the video to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the video caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the video caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5902,7 +5906,7 @@ def __init__(self, id: str, video_file_id: str, title: str, description: Optiona caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None, show_caption_above_media: Optional[bool] = None): - + InlineQueryResultCachedBase.__init__(self) self.type: str = 'video' self.id: str = id @@ -5940,11 +5944,11 @@ class InlineQueryResultCachedVoice(InlineQueryResultCachedBase): :param caption: Optional. Caption, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the voice message caption. See formatting options for + :param parse_mode: Optional. Mode for parsing entities in the voice message caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -5957,7 +5961,7 @@ class InlineQueryResultCachedVoice(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedVoice` """ - + def __init__(self, id: str, voice_file_id: str, title: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): @@ -5972,7 +5976,7 @@ def __init__(self, id: str, voice_file_id: str, title: str, caption: Optional[st self.input_message_content: Optional[InputMessageContent] = input_message_content self.parse_mode: Optional[str] = parse_mode self.payload_dic['voice_file_id'] = voice_file_id - + # noinspection PyUnresolvedReferences,PyShadowingBuiltins @@ -5994,11 +5998,11 @@ class InlineQueryResultCachedAudio(InlineQueryResultCachedBase): :param caption: Optional. Caption, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the audio caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the audio caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -6011,7 +6015,7 @@ class InlineQueryResultCachedAudio(InlineQueryResultCachedBase): :return: Instance of the class :rtype: :class:`telebot.types.InlineQueryResultCachedAudio` """ - + def __init__(self, id: str, audio_file_id: str, caption: Optional[str] = None, caption_entities: Optional[List[MessageEntity]] = None, parse_mode: Optional[str] = None, reply_markup: Optional[InlineKeyboardMarkup] = None, input_message_content: Optional[InputMessageContent] = None): @@ -6044,8 +6048,8 @@ class Game(JsonDeserializable): :param photo: Photo that will be displayed in the game message in chats. :type photo: :obj:`list` of :class:`telebot.types.PhotoSize` - :param text: Optional. Brief description of the game or high scores included in the game message. Can be - automatically edited to include current high scores for the game when the bot calls setGameScore, or manually edited + :param text: Optional. Brief description of the game or high scores included in the game message. Can be + automatically edited to include current high scores for the game when the bot calls setGameScore, or manually edited using editMessageText. 0-4096 characters. :type text: :obj:`str` @@ -6107,7 +6111,7 @@ class Animation(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -6129,8 +6133,8 @@ class Animation(JsonDeserializable): :param mime_type: Optional. MIME type of the file as defined by sender :type mime_type: :obj:`str` - :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have - difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or + :param file_size: Optional. File size in bytes. It can be bigger than 2^31 and some programming languages may have + difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this value. :type file_size: :obj:`int` @@ -6147,7 +6151,7 @@ def de_json(cls, json_string): obj['thumbnail'] = None return cls(**obj) - def __init__(self, file_id, file_unique_id, width=None, height=None, duration=None, + def __init__(self, file_id, file_unique_id, width=None, height=None, duration=None, thumbnail=None, file_name=None, mime_type=None, file_size=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id @@ -6207,8 +6211,8 @@ class LabeledPrice(JsonSerializable, Dictionaryable): :param label: Portion label :type label: :obj:`str` - :param amount: Price of the product in the smallest units of the currency (integer, not float/double). For example, - for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past + :param amount: Price of the product in the smallest units of the currency (integer, not float/double). For example, + for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). :type amount: :obj:`int` @@ -6246,8 +6250,8 @@ class Invoice(JsonDeserializable): :param currency: Three-letter ISO 4217 currency code :type currency: :obj:`str` - :param total_amount: Total price in the smallest units of the currency (integer, not float/double). For example, - for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past + :param total_amount: Total price in the smallest units of the currency (integer, not float/double). For example, + for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). :type total_amount: :obj:`int` @@ -6372,7 +6376,7 @@ def __init__(self, id, title): def add_price(self, *args) -> 'ShippingOption': """ Add LabeledPrice to ShippingOption - + :param args: LabeledPrices :type args: :obj:`LabeledPrice` @@ -6399,8 +6403,8 @@ class SuccessfulPayment(JsonDeserializable): :param currency: Three-letter ISO 4217 currency code :type currency: :obj:`str` - :param total_amount: Total price in the smallest units of the currency (integer, not float/double). For example, - for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past + :param total_amount: Total price in the smallest units of the currency (integer, not float/double). For example, + for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). :type total_amount: :obj:`int` @@ -6439,7 +6443,7 @@ def de_json(cls, json_string): return cls(**obj) def __init__(self, currency, total_amount, invoice_payload, shipping_option_id=None, order_info=None, - telegram_payment_charge_id=None, provider_payment_charge_id=None, + telegram_payment_charge_id=None, provider_payment_charge_id=None, subscription_expiration_date=None, is_recurring=None, is_first_recurring=None, **kwargs): self.currency: str = currency self.total_amount: int = total_amount @@ -6506,8 +6510,8 @@ class PreCheckoutQuery(JsonDeserializable): :param currency: Three-letter ISO 4217 currency code :type currency: :obj:`str` - :param total_amount: Total price in the smallest units of the currency (integer, not float/double). For example, - for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past + :param total_amount: Total price in the smallest units of the currency (integer, not float/double). For example, + for a price of US$ 1.45 pass amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). :type total_amount: :obj:`int` @@ -6619,7 +6623,7 @@ class Sticker(JsonDeserializable): :param file_id: Identifier for this file, which can be used to download or reuse the file :type file_id: :obj:`str` - :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different + :param file_unique_id: Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file. :type file_unique_id: :obj:`str` @@ -6683,8 +6687,8 @@ def de_json(cls, json_string): obj['premium_animation'] = File.de_json(obj['premium_animation']) return cls(**obj) - def __init__(self, file_id, file_unique_id, type, width, height, is_animated, - is_video, thumbnail=None, emoji=None, set_name=None, mask_position=None, file_size=None, + def __init__(self, file_id, file_unique_id, type, width, height, is_animated, + is_video, thumbnail=None, emoji=None, set_name=None, mask_position=None, file_size=None, premium_animation=None, custom_emoji_id=None, needs_repainting=None, **kwargs): self.file_id: str = file_id self.file_unique_id: str = file_unique_id @@ -6714,15 +6718,15 @@ class MaskPosition(Dictionaryable, JsonDeserializable, JsonSerializable): Telegram Documentation: https://core.telegram.org/bots/api#maskposition - :param point: The part of the face relative to which the mask should be placed. One of “forehead”, “eyes”, “mouth”, or + :param point: The part of the face relative to which the mask should be placed. One of “forehead”, “eyes”, “mouth”, or “chin”. :type point: :obj:`str` - :param x_shift: Shift by X-axis measured in widths of the mask scaled to the face size, from left to right. For example, + :param x_shift: Shift by X-axis measured in widths of the mask scaled to the face size, from left to right. For example, choosing -1.0 will place mask just to the left of the default mask position. :type x_shift: :obj:`float` number - :param y_shift: Shift by Y-axis measured in heights of the mask scaled to the face size, from top to bottom. For + :param y_shift: Shift by Y-axis measured in heights of the mask scaled to the face size, from top to bottom. For example, 1.0 will place the mask just below the default mask position. :type y_shift: :obj:`float` number @@ -6790,6 +6794,10 @@ def __init__(self, type, media, caption=None, parse_mode=None, caption_entities= self._media_name = service_utils.generate_random_token() self._media_dic = 'attach://{0}'.format(self._media_name) + if self.__class__ is InputMedia: + # Make InputMedia as ABC some time... + log_deprecation_warning('The InputMedia class should not be instantiated directly. Use particular InputMediaXXX class instead') + def to_json(self): return json.dumps(self.to_dict()) @@ -6811,7 +6819,7 @@ def convert_input_media(self): """ if service_utils.is_string(self.media): return self.to_json(), None - + media_dict = {self._media_name: self.media} if self._thumbnail_name: media_dict[self._thumbnail_name] = self.thumbnail @@ -6825,19 +6833,19 @@ class InputMediaPhoto(InputMedia): Telegram Documentation: https://core.telegram.org/bots/api#inputmediaphoto - :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an - HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using + :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an + HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under name. More information on Sending Files » :type media: :obj:`str` :param caption: Optional. Caption of the photo to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the photo caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the photo caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -6855,7 +6863,7 @@ def __init__(self, media: Union[str, InputFile], caption: Optional[str] = None, has_spoiler: Optional[bool] = None, show_caption_above_media: Optional[bool] = None): if service_utils.is_pil_image(media): media = service_utils.pil_image_to_file(media) - + super(InputMediaPhoto, self).__init__( type="photo", media=media, caption=caption, parse_mode=parse_mode, caption_entities=caption_entities) @@ -6877,15 +6885,15 @@ class InputMediaVideo(InputMedia): Telegram Documentation: https://core.telegram.org/bots/api#inputmediavideo - :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an - HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using + :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an + HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under name. More information on Sending Files » :type media: :obj:`str` - :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported - server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should - not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be - only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using + :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported + server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should + not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be + only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . More information on Sending Files » :type thumbnail: InputFile or :obj:`str` @@ -6900,11 +6908,11 @@ class InputMediaVideo(InputMedia): :param caption: Optional. Caption of the video to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the video caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the video caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -6979,26 +6987,26 @@ class InputMediaAnimation(InputMedia): Telegram Documentation: https://core.telegram.org/bots/api#inputmediaanimation - :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an - HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using + :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an + HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under name. More information on Sending Files » :type media: :obj:`str` :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported - server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should - not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be - only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using + server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should + not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be + only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . More information on Sending Files » :type thumbnail: InputFile or :obj:`str` :param caption: Optional. Caption of the animation to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the animation caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the animation caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -7061,26 +7069,26 @@ class InputMediaAudio(InputMedia): Telegram Documentation: https://core.telegram.org/bots/api#inputmediaaudio - :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an - HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using + :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an + HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under name. More information on Sending Files » :type media: :obj:`str` - :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported - server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should - not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be - only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using + :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported + server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should + not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be + only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . More information on Sending Files » :type thumbnail: InputFile or :obj:`str` :param caption: Optional. Caption of the audio to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the audio caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the audio caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` @@ -7129,29 +7137,29 @@ class InputMediaDocument(InputMedia): Telegram Documentation: https://core.telegram.org/bots/api#inputmediadocument :param media: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an - HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using + HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under name. More information on Sending Files » :type media: :obj:`str` - :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported - server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should - not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be - only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using + :param thumbnail: Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported + server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should + not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be + only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . More information on Sending Files » :type thumbnail: InputFile or :obj:`str` :param caption: Optional. Caption of the document to be sent, 0-1024 characters after entities parsing :type caption: :obj:`str` - :param parse_mode: Optional. Mode for parsing entities in the document caption. See formatting options for more + :param parse_mode: Optional. Mode for parsing entities in the document caption. See formatting options for more details. :type parse_mode: :obj:`str` - :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified + :param caption_entities: Optional. List of special entities that appear in the caption, which can be specified instead of parse_mode :type caption_entities: :obj:`list` of :class:`telebot.types.MessageEntity` - :param disable_content_type_detection: Optional. Disables automatic server-side content type detection for + :param disable_content_type_detection: Optional. Disables automatic server-side content type detection for files uploaded using multipart/form-data. Always True, if the document is sent as part of an album. :type disable_content_type_detection: :obj:`bool` @@ -7374,8 +7382,7 @@ class PollAnswer(JsonSerializable, JsonDeserializable, Dictionaryable): :param user: Optional. The user, who changed the answer to the poll :type user: :class:`telebot.types.User` - :param option_ids: 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted - their vote. + :param option_ids: 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote. :type option_ids: :obj:`list` of :obj:`int` :return: Instance of the class @@ -7394,7 +7401,7 @@ def de_json(cls, json_string): def __init__(self, poll_id: str, option_ids: List[int], user: Optional[User] = None, voter_chat: Optional[Chat] = None, **kwargs): self.poll_id: str = poll_id self.user: Optional[User] = user - self.option_ids: Optional[List[int]] = option_ids + self.option_ids: [List[int]] = option_ids self.voter_chat: Optional[Chat] = voter_chat @@ -7412,7 +7419,7 @@ def to_dict(self): if self.voter_chat: json_dict["voter_chat"] = self.voter_chat return json_dict - + class ChatLocation(JsonSerializable, JsonDeserializable, Dictionaryable): @@ -7436,14 +7443,14 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['location'] = Location.de_json(obj['location']) return cls(**obj) - + def __init__(self, location: Location, address: str, **kwargs): self.location: Location = location self.address: str = address def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): return { "location": self.location.to_dict(), @@ -7457,7 +7464,7 @@ class ChatInviteLink(JsonSerializable, JsonDeserializable, Dictionaryable): Telegram Documentation: https://core.telegram.org/bots/api#chatinvitelink - :param invite_link: The invite link. If the link was created by another chat administrator, then the second part of + :param invite_link: The invite link. If the link was created by another chat administrator, then the second part of the link will be replaced with “…”. :type invite_link: :obj:`str` @@ -7479,7 +7486,7 @@ class ChatInviteLink(JsonSerializable, JsonDeserializable, Dictionaryable): :param expire_date: Optional. Point in time (Unix timestamp) when the link will expire or has been expired :type expire_date: :obj:`int` - :param member_limit: Optional. The maximum number of users that can be members of the chat simultaneously after + :param member_limit: Optional. The maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; 1-99999 :type member_limit: :obj:`int` @@ -7495,7 +7502,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['creator'] = User.de_json(obj['creator']) return cls(**obj) - + def __init__(self, invite_link: str, creator: User, creates_join_request: bool, is_primary: bool, is_revoked: bool, name: Optional[str] = None, expire_date: Optional[int] = None, member_limit: Optional[int] = None, pending_join_request_count: Optional[int] = None, **kwargs): @@ -7508,10 +7515,10 @@ def __init__(self, invite_link: str, creator: User, creates_join_request: bool, self.expire_date: Optional[int] = expire_date self.member_limit: Optional[int] = member_limit self.pending_join_request_count: Optional[int] = pending_join_request_count - + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): json_dict = { "invite_link": self.invite_link, @@ -7554,7 +7561,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - + def __init__(self, traveler, watcher, distance, **kwargs): self.traveler: User = traveler self.watcher: User = watcher @@ -7568,7 +7575,7 @@ class VideoChatStarted(JsonDeserializable): @classmethod def de_json(cls, json_string): return cls() - + def __init__(self): pass @@ -7588,7 +7595,7 @@ class VideoChatScheduled(JsonDeserializable): Telegram Documentation: https://core.telegram.org/bots/api#videochatscheduled - :param start_date: Point in time (Unix timestamp) when the video chat is supposed to be started by a chat + :param start_date: Point in time (Unix timestamp) when the video chat is supposed to be started by a chat administrator :type start_date: :obj:`int` @@ -7600,7 +7607,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - + def __init__(self, start_date, **kwargs): self.start_date: int = start_date @@ -7631,7 +7638,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string, dict_copy=False) return cls(**obj) - + def __init__(self, duration, **kwargs): self.duration: int = duration @@ -7664,7 +7671,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['users'] = [User.de_json(u) for u in obj['users']] return cls(**obj) - + def __init__(self, users=None, **kwargs): self.users: List[User] = users @@ -7689,7 +7696,7 @@ class MessageAutoDeleteTimerChanged(JsonDeserializable): :return: Instance of the class :rtype: :class:`telebot.types.MessageAutoDeleteTimerChanged` - """ + """ @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -7707,7 +7714,7 @@ class MenuButton(JsonDeserializable, JsonSerializable, Dictionaryable): * :class:`MenuButtonCommands` * :class:`MenuButtonWebApp` * :class:`MenuButtonDefault` - + If a menu button other than MenuButtonDefault is set for a private chat, then it is applied in the chat. Otherwise the default menu button is applied. By default, the menu button opens the list of bot commands. """ @@ -7721,7 +7728,7 @@ def de_json(cls, json_string): 'default': MenuButtonDefault } return types[obj['type']](**obj) - + def to_json(self): """ :meta private: @@ -7754,7 +7761,7 @@ def __init__(self, type: str = None, **kwargs): def to_dict(self): return {'type': self.type} - + def to_json(self): return json.dumps(self.to_dict()) @@ -7772,7 +7779,7 @@ class MenuButtonWebApp(MenuButton): :param text: Text on the button :type text: :obj:`str` - :param web_app: Description of the Web App that will be launched when the user presses the button. The Web App will be + :param web_app: Description of the Web App that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Alternatively, a t.me link to a Web App of the bot can be specified in the object instead of the Web App's URL, in which case the Web App will be opened as if the user pressed the link. @@ -7816,7 +7823,7 @@ def to_dict(self): def to_json(self): return json.dumps(self.to_dict()) - + class ChatAdministratorRights(JsonDeserializable, JsonSerializable, Dictionaryable): """ Represents the rights of an administrator in a chat. @@ -7826,8 +7833,8 @@ class ChatAdministratorRights(JsonDeserializable, JsonSerializable, Dictionaryab :param is_anonymous: True, if the user's presence in the chat is hidden :type is_anonymous: :obj:`bool` - :param can_manage_chat: True, if the administrator can access the chat event log, chat statistics, message - statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. + :param can_manage_chat: True, if the administrator can access the chat event log, chat statistics, message + statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege :type can_manage_chat: :obj:`bool` @@ -7840,8 +7847,8 @@ class ChatAdministratorRights(JsonDeserializable, JsonSerializable, Dictionaryab :param can_restrict_members: True, if the administrator can restrict, ban or unban chat members :type can_restrict_members: :obj:`bool` - :param can_promote_members: True, if the administrator can add new administrators with a subset of their own - privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that + :param can_promote_members: True, if the administrator can add new administrators with a subset of their own + privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by the user) :type can_promote_members: :obj:`bool` @@ -7854,7 +7861,7 @@ class ChatAdministratorRights(JsonDeserializable, JsonSerializable, Dictionaryab :param can_post_messages: Optional. True, if the administrator can post in the channel; channels only :type can_post_messages: :obj:`bool` - :param can_edit_messages: Optional. True, if the administrator can edit messages of other users and can pin + :param can_edit_messages: Optional. True, if the administrator can edit messages of other users and can pin messages; channels only :type can_edit_messages: :obj:`bool` @@ -7883,7 +7890,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) return cls(**obj) - def __init__(self, is_anonymous: bool, can_manage_chat: bool, + def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_delete_messages: bool, can_manage_video_chats: bool, can_restrict_members: bool, can_promote_members: bool, can_change_info: bool, can_invite_users: bool, can_post_messages: Optional[bool]=None, can_edit_messages: Optional[bool]=None, @@ -7891,7 +7898,7 @@ def __init__(self, is_anonymous: bool, can_manage_chat: bool, can_post_stories: Optional[bool]=None, can_edit_stories: Optional[bool]=None, can_delete_stories: Optional[bool]=None, **kwargs ) -> None: - + self.is_anonymous: bool = is_anonymous self.can_manage_chat: bool = can_manage_chat self.can_delete_messages: bool = can_delete_messages @@ -7935,17 +7942,17 @@ def to_dict(self): json_dict['can_delete_stories'] = self.can_delete_stories return json_dict - + def to_json(self): return json.dumps(self.to_dict()) - + class InputFile: """ A class to send files through Telegram Bot API. - You need to pass a file, which should be an instance of :class:`io.IOBase` or + You need to pass a file, which should be an instance of :class:`io.IOBase` or :class:`pathlib.Path`, or :obj:`str`. If you pass an :obj:`str` as a file, it will be opened and closed by the class. @@ -7982,7 +7989,7 @@ def __init__(self, file: Union[str, IOBase, Path], file_name: Optional[str] = No self._file, self._file_name = self._resolve_file(file) if file_name: self._file_name = file_name - + @staticmethod def _resolve_file(file): @@ -8003,7 +8010,7 @@ def file(self) -> Union[IOBase, str]: File object. """ return self._file - + @property def file_name(self) -> str: """ @@ -8015,7 +8022,7 @@ def file_name(self) -> str: class ForumTopicCreated(JsonDeserializable): """ This object represents a service message about a new forum topic created in the chat. - + Telegram documentation: https://core.telegram.org/bots/api#forumtopiccreated :param name: Name of the topic @@ -8045,7 +8052,7 @@ def __init__(self, name: str, icon_color: int, icon_custom_emoji_id: Optional[st class ForumTopicClosed(JsonDeserializable): """ This object represents a service message about a forum topic closed in the chat. Currently holds no information. - + Telegram documentation: https://core.telegram.org/bots/api#forumtopicclosed """ # for future use @@ -8117,7 +8124,7 @@ class GeneralForumTopicUnhidden(JsonDeserializable): Telegram documentation: https://core.telegram.org/bots/api#generalforumtopicunhidden """ - + @classmethod def de_json(cls, json_string): return cls() @@ -8186,7 +8193,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + def __init__(self, from_request: Optional[bool]=None, web_app_name: Optional[str]=None, from_attachment_menu: Optional[bool]=None, **kwargs) -> None: @@ -8292,7 +8299,7 @@ class InputSticker(Dictionaryable, JsonSerializable): :param sticker: The added sticker. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. - Animated and video stickers can't be uploaded via HTTP URL. + Animated and video stickers can't be uploaded via HTTP URL. :type sticker: :obj:`str` or :obj:`telebot.types.InputFile` :param emoji_list: One or more(up to 20) emoji(s) corresponding to the sticker @@ -8300,7 +8307,7 @@ class InputSticker(Dictionaryable, JsonSerializable): :param mask_position: Optional. Position where the mask should be placed on faces. For “mask” stickers only. :type mask_position: :class:`telebot.types.MaskPosition` - + :param keywords: Optional. List of 0-20 search keywords for the sticker with total length of up to 64 characters. For “regular” and “custom_emoji” stickers only. :type keywords: :obj:`list` of :obj:`str` @@ -8347,18 +8354,18 @@ def to_dict(self) -> dict: json_dict['keywords'] = self.keywords return json_dict - + def to_json(self) -> str: return json.dumps(self.to_dict()) - + def convert_input_sticker(self) -> Tuple[str, Optional[dict]]: if service_utils.is_string(self.sticker): return self.to_json(), None return self.to_json(), {self._sticker_name: self.sticker} - - - + + + class SwitchInlineQueryChosenChat(JsonDeserializable, Dictionaryable, JsonSerializable): """ Represents an inline button that switches the current user to inline mode in a chosen chat, @@ -8457,7 +8464,7 @@ class InlineQueryResultsButton(JsonSerializable, Dictionaryable): :param web_app: Optional. Description of the Web App that will be launched when the user presses the button. The Web App will be able to switch back to the inline mode using the method web_app_switch_inline_query inside the Web App. :type web_app: :class:`telebot.types.WebAppInfo` - + :param start_parameter: Optional. Deep-linking parameter for the /start message sent to the bot when a user presses the button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed. Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube account to adapt search @@ -8487,7 +8494,7 @@ def to_dict(self) -> dict: json_dict['start_parameter'] = self.start_parameter return json_dict - + def to_json(self) -> str: return json.dumps(self.to_dict()) @@ -8515,7 +8522,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) - + def __init__(self, chat: Chat, id: int, **kwargs) -> None: self.chat: Chat = chat self.id: int = id @@ -8540,23 +8547,30 @@ class ReactionType(JsonDeserializable, Dictionaryable, JsonSerializable): def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) - # remove type + # remove type if obj['type'] == 'emoji': del obj['type'] return ReactionTypeEmoji(**obj) elif obj['type'] == 'custom_emoji': del obj['type'] return ReactionTypeCustomEmoji(**obj) + elif obj['type'] == 'paid': + del obj['type'] + return ReactionTypePaid(**obj) + else: + raise ValueError(f"Unknown reaction type: {obj['type']}.") def __init__(self, type: str) -> None: self.type: str = type + if self.__class__ is ReactionType: + log_deprecation_warning('The ReactionType class should not be instantiated directly. Use particular ReactionTypeXXX class instead') def to_dict(self) -> dict: json_dict = { 'type': self.type } return json_dict - + def to_json(self) -> str: return json.dumps(self.to_dict()) @@ -8633,7 +8647,7 @@ def __init__(self, **kwargs) -> None: def to_dict(self) -> dict: return super().to_dict() - + class MessageReactionUpdated(JsonDeserializable): @@ -8753,7 +8767,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['type'] = ReactionType.de_json(obj['type']) return cls(**obj) - + def __init__(self, type: ReactionType, total_count: int, **kwargs) -> None: self.type: ReactionType = type self.total_count: int = total_count @@ -8935,7 +8949,7 @@ def __init__( # noinspection PyUnresolvedReferences,PyShadowingBuiltins -class MessageOrigin(JsonDeserializable): +class MessageOrigin(JsonDeserializable, ABC): """ This object describes the origin of a message. @@ -8979,6 +8993,8 @@ def de_json(cls, json_string): elif message_type == 'channel': chat = Chat.de_json(obj['chat']) return MessageOriginChannel(date=obj['date'], chat=chat, message_id=obj['message_id'], author_signature=obj.get('author_signature')) + else: + raise ValueError(f"Unknown message origin type: {message_type}.") def __init__(self, type: str, date: int) -> None: self.type: str = type @@ -9165,7 +9181,7 @@ def __init__(self, chats: List[Chat], winners_selection_date: int, winner_count: self.country_codes: Optional[List[str]] = country_codes self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count self.prize_star_count: Optional[int] = prize_star_count - + class GiveawayWinners(JsonDeserializable): """ @@ -9220,7 +9236,7 @@ def de_json(cls, json_string): obj['chat'] = Chat.de_json(obj['chat']) obj['winners'] = [User.de_json(user) for user in obj['winners']] return cls(**obj) - + def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: int, winner_count: int, winners: List[User], additional_chat_count: Optional[int] = None, premium_subscription_month_count: Optional[int] = None, unclaimed_prize_count: Optional[int] = None, @@ -9238,8 +9254,8 @@ def __init__(self, chat: Chat, giveaway_message_id: int, winners_selection_date: self.was_refunded: Optional[bool] = was_refunded self.prize_description: Optional[str] = prize_description self.prize_star_count: Optional[int] = prize_star_count - - + + class GiveawayCompleted(JsonDeserializable): """ This object represents a service message about the completion of a giveaway without public winners. @@ -9269,14 +9285,14 @@ def de_json(cls, json_string): if 'giveaway_message' in obj: obj['giveaway_message'] = Message.de_json(obj['giveaway_message']) return cls(**obj) - + def __init__(self, winner_count: int, unclaimed_prize_count: Optional[int] = None, giveaway_message: Optional[Message] = None, is_star_giveaway: Optional[bool] = None, **kwargs) -> None: self.winner_count: int = winner_count self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count self.giveaway_message: Optional[Message] = giveaway_message self.is_star_giveaway: Optional[bool] = is_star_giveaway - + class GiveawayCreated(JsonDeserializable): """ @@ -9383,7 +9399,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'quote_entities' in obj: obj['quote_entities'] = [MessageEntity.de_json(entity) for entity in obj['quote_entities']] - return cls(**obj) + return cls(**obj) def __init__(self, message_id: int, chat_id: Optional[Union[int, str]] = None, allow_sending_without_reply: Optional[bool] = None, quote: Optional[str] = None, @@ -9414,11 +9430,11 @@ def to_dict(self) -> dict: if self.quote_position is not None: json_dict['quote_position'] = self.quote_position return json_dict - + def to_json(self) -> str: return json.dumps(self.to_dict()) - - + + class UsersShared(JsonDeserializable): """ This object contains information about the users whose identifiers were shared with the bot @@ -9476,7 +9492,7 @@ class ChatBoostUpdated(JsonDeserializable): @classmethod def de_json(cls, json_string): if json_string is None: return None - obj = cls.check_json(json_string) + obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) obj['boost'] = ChatBoost.de_json(obj['boost']) return cls(**obj) @@ -9484,8 +9500,8 @@ def de_json(cls, json_string): def __init__(self, chat, boost, **kwargs): self.chat: Chat = chat self.boost: ChatBoost = boost - - + + class ChatBoostRemoved(JsonDeserializable): """ This object represents a boost removed from a chat. @@ -9513,7 +9529,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) - obj['source'] = ChatBoostSource.de_json(obj['source']) + obj['source'] = ChatBoostSource.de_json(obj['source']) return cls(**obj) def __init__(self, chat, boost_id, remove_date, source, **kwargs): @@ -9521,8 +9537,8 @@ def __init__(self, chat, boost_id, remove_date, source, **kwargs): self.boost_id: str = boost_id self.remove_date: int = remove_date self.source: ChatBoostSource = source - - + + class ChatBoostSource(ABC, JsonDeserializable): """ This object describes the source of a chat boost. It can be one of @@ -9695,7 +9711,7 @@ def __init__(self, boost_id, add_date, expiration_date, source, **kwargs): self.add_date: int = add_date self.expiration_date: int = expiration_date self.source: ChatBoostSource = source - + class UserChatBoosts(JsonDeserializable): """ @@ -9719,7 +9735,7 @@ def de_json(cls, json_string): def __init__(self, boosts, **kwargs): self.boosts: List[ChatBoost] = boosts - + class InaccessibleMessage(JsonDeserializable): """ @@ -9796,7 +9812,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + def __init__(self, boost_count, **kwargs): self.boost_count: int = boost_count @@ -9840,7 +9856,7 @@ def de_json(cls, json_string): obj['user'] = User.de_json(obj['user']) obj['rights'] = BusinessBotRights.de_json(obj.get('rights')) return cls(**obj) - + def __init__(self, id, user, user_chat_id, date, can_reply, is_enabled, rights=None, **kwargs): self.id: str = id @@ -9885,13 +9901,13 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['chat'] = Chat.de_json(obj['chat']) return cls(**obj) - + def __init__(self, business_connection_id, chat, message_ids, **kwargs): self.business_connection_id: str = business_connection_id self.chat: Chat = chat self.message_ids: List[int] = message_ids - + class BusinessIntro(JsonDeserializable): """ @@ -9919,7 +9935,7 @@ def de_json(cls, json_string): if 'sticker' in obj: obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + def __init__(self, title=None, message=None, sticker=None, **kwargs): self.title: Optional[str] = title self.message: Optional[str] = message @@ -9949,7 +9965,7 @@ def de_json(cls, json_string): if 'location' in obj: obj['location'] = Location.de_json(obj['location']) return cls(**obj) - + def __init__(self, address, location=None, **kwargs): self.address: str = address self.location: Optional[Location] = location @@ -9976,7 +9992,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + def __init__(self, opening_minute, closing_minute, **kwargs): self.opening_minute: int = opening_minute self.closing_minute: int = closing_minute @@ -10006,7 +10022,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['opening_hours'] = [BusinessOpeningHoursInterval.de_json(interval) for interval in obj['opening_hours']] return cls(**obj) - + def __init__(self, time_zone_name, opening_hours, **kwargs): self.time_zone_name: str = time_zone_name self.opening_hours: List[BusinessOpeningHoursInterval] = opening_hours @@ -10044,7 +10060,7 @@ def de_json(cls, json_string): if 'photo' in obj: obj['photo'] = [PhotoSize.de_json(photo) for photo in obj['photo']] return cls(**obj) - + def __init__(self, user_id, first_name=None, last_name=None, username=None, photo=None, **kwargs): self.user_id: int = user_id self.first_name: Optional[str] = first_name @@ -10077,7 +10093,7 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + def __init__(self, day, month, year=None, **kwargs): self.day: int = day self.month: int = month @@ -10513,13 +10529,17 @@ def de_json(cls, json_string): return cls(**obj) -class TransactionPartner(JsonDeserializable): +class TransactionPartner(JsonDeserializable, ABC): # noinspection PyUnresolvedReferences """ This object describes the source of a transaction, or its recipient for outgoing transactions. Currently, it can be one of TransactionPartnerFragment TransactionPartnerUser TransactionPartnerOther + TransactionPartnerTelegramAds + TransactionPartnerTelegramApi + TransactionPartnerAffiliateProgram + TransactionPartnerChat Telegram documentation: https://core.telegram.org/bots/api#transactionpartner @@ -10548,6 +10568,8 @@ def de_json(cls, json_string): return TransactionPartnerOther.de_json(obj) elif obj["type"] == "chat": return TransactionPartnerChat.de_json(obj) + else: + raise ValueError(f"Unknown transaction partner type: {obj['type']}") # noinspection PyShadowingBuiltins @@ -10581,6 +10603,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class TransactionPartnerTelegramApi(TransactionPartner): """ Describes a transaction with payment for paid broadcasting. @@ -10648,8 +10671,8 @@ class TransactionPartnerUser(TransactionPartner): :rtype: :class:`TransactionPartnerUser` """ - def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, - subscription_period=None, gift: Optional[Gift] = None, premium_subscription_duration: Optional[int] = None, + def __init__(self, type, user, affiliate=None, invoice_payload=None, paid_media: Optional[List[PaidMedia]] = None, + subscription_period=None, gift: Optional[Gift] = None, premium_subscription_duration: Optional[int] = None, transaction_type: Optional[str] = None, **kwargs): self.type: str = type self.user: User = user @@ -10681,7 +10704,7 @@ class TransactionPartnerTelegramAds(TransactionPartner): Describes a transaction with Telegram Ads. Telegram documentation: https://core.telegram.org/bots/api#transactionpartnertelegramads - + :param type: Type of the transaction partner, always “telegram_ads” :type type: :obj:`str` @@ -10761,7 +10784,7 @@ def de_json(cls, json_string): if 'receiver' in obj: obj['receiver'] = TransactionPartner.de_json(obj['receiver']) return cls(**obj) - + def __init__(self, id, amount, date, source=None, receiver=None, nanostar_amount=None, **kwargs): self.id: str = id self.amount: int = amount @@ -10791,12 +10814,12 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['transactions'] = [StarTransaction.de_json(transaction) for transaction in obj['transactions']] return cls(**obj) - + def __init__(self, transactions, **kwargs): self.transactions: List[StarTransaction] = transactions -class PaidMedia(JsonDeserializable): +class PaidMedia(JsonDeserializable, ABC): """ This object describes paid media. Currently, it can be one of @@ -10820,6 +10843,8 @@ def de_json(cls, json_string): return PaidMediaPhoto.de_json(obj) elif obj["type"] == "video": return PaidMediaVideo.de_json(obj) + else: + raise ValueError("Unknown type of PaidMedia: {0}".format(obj["type"])) # noinspection PyShadowingBuiltins @@ -10940,14 +10965,14 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['paid_media'] = [PaidMedia.de_json(media) for media in obj['paid_media']] return cls(**obj) - + def __init__(self, star_count, paid_media, **kwargs): self.star_count: int = star_count self.paid_media: List[PaidMedia] = paid_media # noinspection PyShadowingBuiltins -class InputPaidMedia(JsonSerializable): +class InputPaidMedia(Dictionaryable, JsonSerializable): """ This object describes the paid media to be sent. Currently, it can be one of InputPaidMediaPhoto @@ -10970,16 +10995,21 @@ def __init__(self, type: str, media: Union[str, InputFile], **kwargs): self._media_name = service_utils.generate_random_token() self._media_dic = 'attach://{0}'.format(self._media_name) + if self.__class__ is InputPaidMedia: + # Make InputPaidMedia as ABC some time... + log_deprecation_warning('The InputPaidMedia class should not be instantiated directly. Use particular InputPaidMediaXXX class instead') + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'type': self.type, 'media': self._media_dic } return data - + + class InputPaidMediaPhoto(InputPaidMedia): """ The paid media to send is a photo. @@ -11000,7 +11030,8 @@ class InputPaidMediaPhoto(InputPaidMedia): def __init__(self, media: Union[str, InputFile], **kwargs): super().__init__(type='photo', media=media) - + + class InputPaidMediaVideo(InputPaidMedia): """ The paid media to send is a video. @@ -11058,8 +11089,6 @@ def __init__(self, media: Union[str, InputFile], thumbnail: Optional[InputFile] self.cover: Optional[Union[str,InputFile]] = cover self.start_timestamp: Optional[int] = start_timestamp - - def to_dict(self): data = super().to_dict() if self.thumbnail: @@ -11078,6 +11107,7 @@ def to_dict(self): data['start_timestamp'] = self.start_timestamp return data + class RefundedPayment(JsonDeserializable): """ This object contains basic information about a refunded payment. @@ -11115,8 +11145,8 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - - + + class PaidMediaPurchased(JsonDeserializable): """ This object contains information about a paid media purchase. @@ -11143,7 +11173,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['from_user'] = User.de_json(obj['from_user']) return cls(**obj) - + class CopyTextButton(JsonSerializable, JsonDeserializable): """ @@ -11162,13 +11192,13 @@ def __init__(self, text: str, **kwargs): def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'text': self.text } return data - + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11176,6 +11206,7 @@ def de_json(cls, json_string): return cls(**obj) +# noinspection PyShadowingBuiltins class PreparedInlineMessage(JsonDeserializable): """ Describes an inline message to be sent by a user of a Mini App. @@ -11201,8 +11232,9 @@ def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + +# noinspection PyShadowingBuiltins class Gift(JsonDeserializable): """ This object represents a gift that can be sent by the bot. @@ -11245,7 +11277,8 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + + class Gifts(JsonDeserializable): """ This object represent a list of gifts. @@ -11268,8 +11301,9 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['gifts'] = [Gift.de_json(gift) for gift in obj['gifts']] return cls(**obj) - - + + +# noinspection PyShadowingBuiltins class TransactionPartnerAffiliateProgram(TransactionPartner): """ Describes the affiliate program that issued the affiliate commission received via this transaction. @@ -11302,7 +11336,7 @@ def de_json(cls, json_string): obj['sponsor_user'] = User.de_json(obj['sponsor_user']) return cls(**obj) - + class AffiliateInfo(JsonDeserializable): """ @@ -11345,8 +11379,9 @@ def de_json(cls, json_string): if 'affiliate_chat' in obj: obj['affiliate_chat'] = Chat.de_json(obj['affiliate_chat']) return cls(**obj) - + +# noinspection PyShadowingBuiltins class TransactionPartnerChat(TransactionPartner): """ Describes a transaction with a chat. @@ -11379,7 +11414,7 @@ def de_json(cls, json_string): if 'gift' in obj: obj['gift'] = Gift.de_json(obj['gift']) return cls(**obj) - + class BusinessBotRights(JsonDeserializable): """ @@ -11430,10 +11465,10 @@ class BusinessBotRights(JsonDeserializable): :type can_manage_stories: :obj:`bool` :return: Instance of the class - :rtype: :class:`BusinessBotRights` + :rtype: :class:`BusinessBotRights` """ def __init__(self, can_reply=None, can_read_messages=None, can_delete_outgoing_messages=None, can_delete_all_messages=None, - can_edit_name=None, can_edit_bio=None, can_edit_profile_photo=None, can_edit_username=None, + can_edit_name=None, can_edit_bio=None, can_edit_profile_photo=None, can_edit_username=None, can_change_gift_settings=None, can_view_gifts_and_stars=None, can_convert_gifts_to_stars=None, can_transfer_and_upgrade_gifts=None, can_transfer_stars=None, can_manage_stories=None, **kwargs): self.can_reply: Optional[bool] = can_reply @@ -11450,7 +11485,7 @@ def __init__(self, can_reply=None, can_read_messages=None, can_delete_outgoing_m self.can_transfer_and_upgrade_gifts: Optional[bool] = can_transfer_and_upgrade_gifts self.can_transfer_stars: Optional[bool] = can_transfer_stars self.can_manage_stories: Optional[bool] = can_manage_stories - + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11472,7 +11507,7 @@ class AcceptedGiftTypes(JsonDeserializable, JsonSerializable): :param unique_gifts: True, if unique gifts or gifts that can be upgraded to unique for free are accepted :type unique_gifts: :obj:`bool` - + :param premium_subscription: True, if a Telegram Premium subscription is accepted :type premium_subscription: :obj:`bool` @@ -11485,10 +11520,10 @@ def __init__(self, unlimited_gifts: bool, limited_gifts: bool, self.limited_gifts: bool = limited_gifts self.unique_gifts: bool = unique_gifts self.premium_subscription: bool = premium_subscription - + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'unlimited_gifts': self.unlimited_gifts, @@ -11497,6 +11532,7 @@ def to_dict(self): 'premium_subscription': self.premium_subscription } return data + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11522,13 +11558,15 @@ class StarAmount(JsonDeserializable): def __init__(self, amount, nanostar_amount=None, **kwargs): self.amount: int = amount self.nanostar_amount: Optional[int] = nanostar_amount + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + +# noinspection PyShadowingBuiltins class OwnedGift(JsonDeserializable, ABC): """ This object describes a gift received and owned by a user or a chat. Currently, it can be one of @@ -11540,9 +11578,8 @@ class OwnedGift(JsonDeserializable, ABC): def __init__(self, type, **kwargs): self.type: str = type - self.gift: Union[Gift, UniqueGift] = None - - + self.gift: Optional[Union[Gift, UniqueGift]] = None + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11551,7 +11588,11 @@ def de_json(cls, json_string): return OwnedGiftRegular.de_json(obj) elif obj["type"] == "unique": return OwnedGiftUnique.de_json(obj) - + else: + raise ValueError(f"Unknown gift type: {obj['type']}.") + + +# noinspection PyShadowingBuiltins class OwnedGiftRegular(OwnedGift): """ This object describes a regular gift owned by a user or a chat. @@ -11572,7 +11613,7 @@ class OwnedGiftRegular(OwnedGift): :param send_date: Date the gift was sent in Unix time :type send_date: :obj:`int` - + :param text: Optional. Text of the message that was added to the gift :type text: :obj:`str` @@ -11616,6 +11657,7 @@ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=N self.was_refunded: Optional[bool] = was_refunded self.convert_star_count: Optional[int] = convert_star_count self.prepaid_upgrade_star_count: Optional[int] = prepaid_upgrade_star_count + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11626,7 +11668,9 @@ def de_json(cls, json_string): if 'entities' in obj: obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] return cls(**obj) - + + +# noinspection PyShadowingBuiltins class OwnedGiftUnique(OwnedGift): """ This object describes a unique gift owned by a user or a chat. @@ -11674,6 +11718,7 @@ def __init__(self, type, gift, owned_gift_id=None, sender_user=None, send_date=N self.can_be_transferred: Optional[bool] = can_be_transferred self.transfer_star_count: Optional[int] = transfer_star_count self.next_transfer_date: Optional[int] = next_transfer_date + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11682,7 +11727,7 @@ def de_json(cls, json_string): if 'sender_user' in obj: obj['sender_user'] = User.de_json(obj['sender_user']) return cls(**obj) - + class OwnedGifts(JsonDeserializable): """ @@ -11707,6 +11752,7 @@ def __init__(self, total_count, gifts, next_offset=None, **kwargs): self.total_count: int = total_count self.gifts: List[OwnedGift] = gifts self.next_offset: Optional[str] = next_offset + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11715,7 +11761,6 @@ def de_json(cls, json_string): return cls(**obj) - class UniqueGift(JsonDeserializable): """ This object describes a unique gift that was upgraded from a regular gift. @@ -11750,6 +11795,7 @@ def __init__(self, base_name, name, number, model, symbol, backdrop, **kwargs): self.model: UniqueGiftModel = model self.symbol: UniqueGiftSymbol = symbol self.backdrop: UniqueGiftBackdrop = backdrop + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11758,8 +11804,8 @@ def de_json(cls, json_string): obj['symbol'] = UniqueGiftSymbol.de_json(obj['symbol']) obj['backdrop'] = UniqueGiftBackdrop.de_json(obj['backdrop']) return cls(**obj) - - + + class UniqueGiftModel(JsonDeserializable): """ This object describes the model of a unique gift. @@ -11783,13 +11829,15 @@ def __init__(self, name, sticker, rarity_per_mille, **kwargs): self.name: str = name self.sticker: Sticker = sticker self.rarity_per_mille: int = rarity_per_mille + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + + class UniqueGiftSymbol(JsonDeserializable): """ This object describes the symbol shown on the pattern of a unique gift. @@ -11813,13 +11861,15 @@ def __init__(self, name, sticker, rarity_per_mille, **kwargs): self.name: str = name self.sticker: Sticker = sticker self.rarity_per_mille: int = rarity_per_mille + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) obj['sticker'] = Sticker.de_json(obj['sticker']) return cls(**obj) - + + class UniqueGiftBackdropColors(JsonDeserializable): """ This object describes the colors of the backdrop of a unique gift. @@ -11846,12 +11896,14 @@ def __init__(self, center_color, edge_color, symbol_color, text_color, **kwargs) self.edge_color: int = edge_color self.symbol_color: int = symbol_color self.text_color: int = text_color + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - + + class UniqueGiftBackdrop(JsonDeserializable): """ This object describes the backdrop of a unique gift. @@ -11874,6 +11926,7 @@ def __init__(self, name, colors, rarity_per_mille, **kwargs): self.name: str = name self.colors: UniqueGiftBackdropColors = colors self.rarity_per_mille: int = rarity_per_mille + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -11881,6 +11934,8 @@ def de_json(cls, json_string): obj['colors'] = UniqueGiftBackdropColors.de_json(obj['colors']) return cls(**obj) + +# noinspection PyShadowingBuiltins class InputStoryContent(JsonSerializable, ABC): """ This object describes the content of a story to post. Currently, it can be one of @@ -11888,7 +11943,6 @@ class InputStoryContent(JsonSerializable, ABC): InputStoryContentVideo Telegram documentation: https://core.telegram.org/bots/api#inputstorycontent - """ def __init__(self, type: str, **kwargs): self.type: str = type @@ -11911,20 +11965,20 @@ def __init__(self, photo: InputFile, **kwargs): self.photo: InputFile = photo self._photo_name = service_utils.generate_random_token() self._photo_dic = "attach://{}".format(self._photo_name) - + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'type': self.type, 'photo': self._photo_dic } return data - + def convert_input_story(self): return self.to_json(), {self._photo_name: self.photo} - + class InputStoryContentVideo(InputStoryContent): """ @@ -11956,9 +12010,10 @@ def __init__(self, video: InputFile, duration: Optional[float] = None, cover_fra self.duration: Optional[float] = duration self.cover_frame_timestamp: Optional[float] = cover_frame_timestamp self.is_animation: Optional[bool] = is_animation + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'type': self.type, @@ -11971,9 +12026,10 @@ def to_dict(self): if self.is_animation is not None: data['is_animation'] = self.is_animation return data + def convert_input_story(self): return self.to_json(), {self._video_name: self.video} - + class StoryAreaPosition(JsonSerializable): """ @@ -12010,8 +12066,10 @@ def __init__(self, x_percentage: float, y_percentage: float, width_percentage: f self.height_percentage: float = height_percentage self.rotation_angle: float = rotation_angle self.corner_radius_percentage: float = corner_radius_percentage + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'x_percentage': self.x_percentage, @@ -12022,7 +12080,7 @@ def to_dict(self): 'corner_radius_percentage': self.corner_radius_percentage } return data - + class LocationAddress(JsonSerializable): """ @@ -12051,8 +12109,10 @@ def __init__(self, country_code: str, state: Optional[str] = None, city: Optiona self.state: Optional[str] = state self.city: Optional[str] = city self.street: Optional[str] = street + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'country_code': self.country_code @@ -12064,7 +12124,9 @@ def to_dict(self): if self.street is not None: data['street'] = self.street return data - + + +# noinspection PyShadowingBuiltins class StoryAreaType(JsonSerializable, ABC): """ Describes the type of a clickable area on a story. Currently, it can be one of @@ -12109,8 +12171,10 @@ def __init__(self,latitude: float, longitude: float, address: LocationAddress = self.latitude: float = latitude self.longitude: float = longitude self.address: Optional[LocationAddress] = address + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12120,7 +12184,7 @@ def to_dict(self): if self.address is not None: data['address'] = self.address.to_dict() return data - + class StoryAreaTypeSuggestedReaction(StoryAreaType): """ @@ -12148,8 +12212,10 @@ def __init__(self, reaction_type: ReactionType, is_dark: Optional[bool] = None, self.reaction_type: ReactionType = reaction_type self.is_dark: Optional[bool] = is_dark self.is_flipped: Optional[bool] = is_flipped + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12160,7 +12226,8 @@ def to_dict(self): if self.is_flipped is not None: data['is_flipped'] = self.is_flipped return data - + + class StoryAreaTypeLink(StoryAreaType): """ Describes a story area pointing to an HTTP or tg:// link. Currently, a story can have up to 3 link areas. @@ -12179,15 +12246,18 @@ class StoryAreaTypeLink(StoryAreaType): def __init__(self, url: str, **kwargs): super().__init__(type="link") self.url: str = url + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, 'url': self.url } return data - + + class StoryAreaTypeWeather(StoryAreaType): """ Describes a story area containing weather information. Currently, a story can have up to 3 weather areas. @@ -12214,8 +12284,10 @@ def __init__(self, temperature: float, emoji: str, background_color: int, **kwar self.temperature: float = temperature self.emoji: str = emoji self.background_color: int = background_color + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12224,7 +12296,8 @@ def to_dict(self): 'background_color': self.background_color } return data - + + class StoryAreaTypeUniqueGift(StoryAreaType): """ Describes a story area pointing to a unique gift. Currently, a story can have at most 1 unique gift area. @@ -12243,8 +12316,10 @@ class StoryAreaTypeUniqueGift(StoryAreaType): def __init__(self, name: str, **kwargs): super().__init__(type="unique_gift") self.name: str = name + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12252,8 +12327,9 @@ def to_dict(self): } return data - + +# noinspection PyShadowingBuiltins class StoryArea(JsonSerializable): """ Describes a clickable area on a story media. @@ -12272,15 +12348,17 @@ class StoryArea(JsonSerializable): def __init__(self, position: StoryAreaPosition, type: StoryAreaType, **kwargs): self.position: StoryAreaPosition = position self.type: StoryAreaType = type + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'position': self.position.to_dict(), 'type': self.type.to_dict() } return data - + class GiftInfo(JsonDeserializable): """ @@ -12327,6 +12405,7 @@ def __init__(self, gift: Gift, owned_gift_id: Optional[str] = None, convert_star self.text: Optional[str] = text self.entities: Optional[List[MessageEntity]] = entities self.is_private: Optional[bool] = is_private + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12335,7 +12414,8 @@ def de_json(cls, json_string): if 'entities' in obj: obj['entities'] = [MessageEntity.de_json(entity) for entity in obj['entities']] return cls(**obj) - + + class UniqueGiftInfo(JsonDeserializable): """ This object describes a service message about a unique gift that was sent or received. @@ -12380,7 +12460,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) obj['gift'] = UniqueGift.de_json(obj['gift']) return cls(**obj) - + class PaidMessagePriceChanged(JsonDeserializable): """ @@ -12396,14 +12476,15 @@ class PaidMessagePriceChanged(JsonDeserializable): """ def __init__(self, paid_message_star_count: int, **kwargs): self.paid_message_star_count: int = paid_message_star_count + @classmethod def de_json(cls, json_string): if json_string is None: return None obj = cls.check_json(json_string) return cls(**obj) - -class InputProfilePhoto(JsonSerializable): + +class InputProfilePhoto(JsonSerializable, ABC): """ This object describes a profile photo to set. Currently, it can be one of InputProfilePhotoStatic @@ -12415,10 +12496,11 @@ class InputProfilePhoto(JsonSerializable): :rtype: :class:`InputProfilePhoto` """ + class InputProfilePhotoStatic(InputProfilePhoto): """ This object describes a static profile photo to set. - + Telegram documentation: https://core.telegram.org/bots/api#inputprofilephotostatic :param type: Type of the profile photo, must be static @@ -12434,18 +12516,19 @@ class InputProfilePhotoStatic(InputProfilePhoto): def __init__(self, photo: InputFile, **kwargs): self.type: str = "static" self.photo: InputFile = photo - self._photo_name = service_utils.generate_random_token() self._photo_dic = "attach://{}".format(self._photo_name) + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'type': self.type, 'photo': self._photo_dic } return data + def convert_input_profile_photo(self): return self.to_json(), {self._photo_name: self.photo} @@ -12475,8 +12558,10 @@ def __init__(self, animation: InputFile, main_frame_timestamp: Optional[float] = self._animation_name = service_utils.generate_random_token() self._animation_dic = "attach://{}".format(self._animation_name) self.main_frame_timestamp: Optional[float] = main_frame_timestamp + def to_json(self): return json.dumps(self.to_dict()) + def to_dict(self): data = { 'type': self.type, @@ -12485,10 +12570,12 @@ def to_dict(self): if self.main_frame_timestamp is not None: data['main_frame_timestamp'] = self.main_frame_timestamp return data + def convert_input_profile_photo(self): return self.to_json(), {self._animation_name: self.animation} +# noinspection PyShadowingBuiltins class ChecklistTask(JsonDeserializable): """ Describes a task in a checklist. @@ -12531,7 +12618,8 @@ def de_json(cls, json_string): if 'completed_by_user' in obj: obj['completed_by_user'] = User.de_json(obj['completed_by_user']) return cls(**obj) - + + class Checklist(JsonDeserializable): """ Describes a checklist. @@ -12557,7 +12645,7 @@ class Checklist(JsonDeserializable): :rtype: :class:`Checklist` """ def __init__(self, title: str, tasks: List[ChecklistTask], - title_entities: Optional[List[MessageEntity]] = None, + title_entities: Optional[List[MessageEntity]] = None, others_can_add_tasks: Optional[bool] = None, others_can_mark_tasks_as_done: Optional[bool] = None, **kwargs): self.title: str = title @@ -12575,6 +12663,8 @@ def de_json(cls, json_string): obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] return cls(**obj) + +# noinspection PyShadowingBuiltins class InputChecklistTask(JsonSerializable): """ Describes a task to add to a checklist. @@ -12602,10 +12692,10 @@ def __init__(self, id: int, text: str, parse_mode: Optional[str] = None, self.text: str = text self.parse_mode: Optional[str] = parse_mode self.text_entities: Optional[List[MessageEntity]] = text_entities - + def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'id': self.id, @@ -12616,7 +12706,8 @@ def to_dict(self): if self.text_entities: data['text_entities'] = [entity.to_dict() for entity in self.text_entities] return data - + + class InputChecklist(JsonSerializable): """ Describes a checklist to create. @@ -12644,7 +12735,7 @@ class InputChecklist(JsonSerializable): :return: Instance of the class :rtype: :class:`InputChecklist` """ - def __init__(self, title: str, tasks: List[InputChecklistTask], + def __init__(self, title: str, tasks: List[InputChecklistTask], parse_mode: Optional[str] = None, title_entities: Optional[List[MessageEntity]] = None, others_can_add_tasks: Optional[bool] = None, @@ -12658,7 +12749,7 @@ def __init__(self, title: str, tasks: List[InputChecklistTask], def to_json(self): return json.dumps(self.to_dict()) - + def to_dict(self): data = { 'title': self.title, @@ -12706,8 +12797,8 @@ def de_json(cls, json_string): if 'checklist_message' in obj: obj['checklist_message'] = Message.de_json(obj['checklist_message']) return cls(**obj) - - + + class ChecklistTasksAdded(JsonDeserializable): """ Describes a service message about tasks added to a checklist. @@ -12726,6 +12817,7 @@ class ChecklistTasksAdded(JsonDeserializable): def __init__(self, tasks: List[ChecklistTask], checklist_message: Optional[Message] = None, **kwargs): self.checklist_message: Optional[Message] = checklist_message self.tasks: List[ChecklistTask] = tasks + @classmethod def de_json(cls, json_string): if json_string is None: return None @@ -12735,6 +12827,7 @@ def de_json(cls, json_string): obj['tasks'] = [ChecklistTask.de_json(task) for task in obj['tasks']] return cls(**obj) + class DirectMessagePriceChanged(JsonDeserializable): """ Describes a service message about a change in the price of direct messages sent to a channel chat. From 220772b0ddbc39d8f820dfdb4288619c0d168734 Mon Sep 17 00:00:00 2001 From: All-The-Foxes <116322192+All-The-Foxes@users.noreply.github.com> Date: Fri, 22 Aug 2025 18:55:42 -0400 Subject: [PATCH 474/480] Fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- telebot/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index 27d6c3f22..926262263 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -7401,7 +7401,7 @@ def de_json(cls, json_string): def __init__(self, poll_id: str, option_ids: List[int], user: Optional[User] = None, voter_chat: Optional[Chat] = None, **kwargs): self.poll_id: str = poll_id self.user: Optional[User] = user - self.option_ids: [List[int]] = option_ids + self.option_ids: List[int] = option_ids self.voter_chat: Optional[Chat] = voter_chat From d3d7a52a4cb618ee64b2b3643d7b883f0187002e Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 28 Aug 2025 21:00:47 +0500 Subject: [PATCH 475/480] Fix missing parameters, inconsistent descriptions, content type services --- telebot/__init__.py | 8 ++++---- telebot/async_telebot.py | 8 ++++---- telebot/types.py | 26 ++++++++++++++++++-------- telebot/util.py | 4 +++- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 679afc311..dcdeb8eb3 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -2010,14 +2010,14 @@ def copy_message( )) - def approve_suggested_post(self, chat_id: Union[int, str], message_id: int, send_date: Optional[int]=None) -> bool: + def approve_suggested_post(self, chat_id: int, message_id: int, send_date: Optional[int]=None) -> bool: """ Use this method to approve a suggested post in a direct messages chat. The bot must have the 'can_post_messages' administrator right in the corresponding channel chat. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#approvesuggestedpost :param chat_id: Unique identifier for the target direct messages chat - :type chat_id: :obj:`int` or :obj:`str` + :type chat_id: :obj:`int` :param message_id: Identifier of a suggested post message to approve :type message_id: :obj:`int` @@ -2032,7 +2032,7 @@ def approve_suggested_post(self, chat_id: Union[int, str], message_id: int, send return apihelper.approve_suggested_post(self.token, chat_id, message_id, send_date=send_date) - def decline_suggested_post(self, chat_id: Union[int, str], message_id: int, comment: Optional[str]=None) -> bool: + def decline_suggested_post(self, chat_id: int, message_id: int, comment: Optional[str]=None) -> bool: """ Use this method to decline a suggested post in a direct messages chat. The bot must have the 'can_manage_direct_messages' administrator right in the corresponding channel chat. Returns True on success. @@ -2040,7 +2040,7 @@ def decline_suggested_post(self, chat_id: Union[int, str], message_id: int, comm Telegram documentation: https://core.telegram.org/bots/api#declinesuggestedpost :param chat_id: Unique identifier for the target direct messages chat - :type chat_id: :obj:`int` or :obj:`str` + :type chat_id: :obj:`int` :param message_id: Identifier of a suggested post message to decline :type message_id: :obj:`int` diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index bc01a012e..33783893f 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -3537,14 +3537,14 @@ async def copy_message( ) ) - async def approve_suggested_post(self, chat_id: Union[int, str], message_id: int, send_date: Optional[int]=None) -> bool: + async def approve_suggested_post(self, chat_id: int, message_id: int, send_date: Optional[int]=None) -> bool: """ Use this method to approve a suggested post in a direct messages chat. The bot must have the 'can_post_messages' administrator right in the corresponding channel chat. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#approvesuggestedpost :param chat_id: Unique identifier for the target direct messages chat - :type chat_id: :obj:`int` or :obj:`str` + :type chat_id: :obj:`int` :param message_id: Identifier of a suggested post message to approve :type message_id: :obj:`int` @@ -3559,7 +3559,7 @@ async def approve_suggested_post(self, chat_id: Union[int, str], message_id: int return await asyncio_helper.approve_suggested_post(self.token, chat_id, message_id, send_date=send_date) - async def decline_suggested_post(self, chat_id: Union[int, str], message_id: int, comment: Optional[str]=None) -> bool: + async def decline_suggested_post(self, chat_id: int, message_id: int, comment: Optional[str]=None) -> bool: """ Use this method to decline a suggested post in a direct messages chat. The bot must have the 'can_manage_direct_messages' administrator right in the corresponding channel chat. Returns True on success. @@ -3567,7 +3567,7 @@ async def decline_suggested_post(self, chat_id: Union[int, str], message_id: int Telegram documentation: https://core.telegram.org/bots/api#declinesuggestedpost :param chat_id: Unique identifier for the target direct messages chat - :type chat_id: :obj:`int` or :obj:`str` + :type chat_id: :obj:`int` :param message_id: Identifier of a suggested post message to decline :type message_id: :obj:`int` diff --git a/telebot/types.py b/telebot/types.py index 33cf8dba6..3f01fec54 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -13097,18 +13097,19 @@ class SuggestedPostApproved(JsonDeserializable): :param price: Optional. Amount paid for the post :type price: :class:`SuggestedPostPrice` - :param send_date: Optional. Date when the post will be published - :type send_date: int + :param send_date: Date when the post will be published + :type send_date: :obj:`int` :return: Instance of the class :rtype: :class:`SuggestedPostApproved` """ - def __init__(self, suggested_post_message: Optional[Message] = None, + def __init__(self, send_date: int, + suggested_post_message: Optional[Message] = None, price: Optional[SuggestedPostPrice] = None, - send_date: Optional[int] = None, **kwargs): + **kwargs): self.suggested_post_message: Optional[Message] = suggested_post_message self.price: Optional[SuggestedPostPrice] = price - self.send_date: Optional[int] = send_date + self.send_date: int = send_date @classmethod def de_json(cls, json_string): @@ -13130,11 +13131,16 @@ class SuggestedPostApprovalFailed(JsonDeserializable): :param suggested_post_message: Optional. Message containing the suggested post whose approval has failed. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. :type suggested_post_message: :class:`Message` + :param price: Expected price of the post + :type price: :class:`SuggestedPostPrice` + :return: Instance of the class :rtype: :class:`SuggestedPostApprovalFailed` """ - def __init__(self, suggested_post_message: Optional[Message] = None, **kwargs): + def __init__(self, price: SuggestedPostPrice, + suggested_post_message: Optional[Message] = None, **kwargs): self.suggested_post_message: Optional[Message] = suggested_post_message + self.price: SuggestedPostPrice = price @classmethod def de_json(cls, json_string): @@ -13142,6 +13148,7 @@ def de_json(cls, json_string): obj = cls.check_json(json_string) if 'suggested_post_message' in obj: obj['suggested_post_message'] = Message.de_json(obj['suggested_post_message']) + obj['price'] = SuggestedPostPrice.de_json(obj['price']) return cls(**obj) class SuggestedPostDeclined(JsonDeserializable): @@ -13153,6 +13160,9 @@ class SuggestedPostDeclined(JsonDeserializable): :param suggested_post_message: Optional. Message containing the suggested post. Note that the Message object in this field will not contain the reply_to_message field even if it itself is a reply. :type suggested_post_message: :class:`Message` + :param comment: Optional. Comment with which the post was declined + :type comment: :obj:`str` + :return: Instance of the class :rtype: :class:`SuggestedPostDeclined` """ @@ -13221,9 +13231,9 @@ class SuggestedPostRefunded(JsonDeserializable): :return: Instance of the class :rtype: :class:`SuggestedPostRefunded` """ - def __init__(self, suggested_post_message: Optional[Message] = None, reason: Optional[str] = None, **kwargs): + def __init__(self, reason: str, suggested_post_message: Optional[Message] = None, **kwargs): self.suggested_post_message: Optional[Message] = suggested_post_message - self.reason: Optional[str] = reason + self.reason: str = reason @classmethod def de_json(cls, json_string): diff --git a/telebot/util.py b/telebot/util.py index 2f92ae781..0d37866e1 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -41,7 +41,9 @@ 'chat_background_set', 'forum_topic_created', 'forum_topic_closed', 'forum_topic_reopened', 'forum_topic_edited', 'general_forum_topic_hidden', 'general_forum_topic_unhidden', 'write_access_allowed', 'users_shared', 'chat_shared', 'giveaway_created', 'giveaway_winners', 'giveaway_completed', 'boost_added', 'paid_message_price_changed', - 'checklist_tasks_done', 'checklist_tasks_added', 'direct_message_price_changed', + 'checklist_tasks_done', 'checklist_tasks_added', 'direct_message_price_changed', 'suggested_post_refunded', + 'suggested_post_info', 'suggested_post_approved', 'suggested_post_approval_failed', 'suggested_post_declined', + 'suggested_post_paid' ] #: All update types, should be used for allowed_updates parameter in polling. From 5f1153a079dddd01d11243d1f9b33e6cecf771d0 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Sat, 30 Aug 2025 10:23:26 +0300 Subject: [PATCH 476/480] Bump version --- docs/source/conf.py | 2 +- pyproject.toml | 4 ++-- telebot/version.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4dcffc212..514d9dad4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.28.0' +release = '4.29.0' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index c46727508..5271bfa16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,8 +4,8 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.28.0" -description = "Python Telegram bot api." +version = "4.29.0" +description = "Python Telegram bot API." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} readme = "README.md" diff --git a/telebot/version.py b/telebot/version.py index c2bb2a64b..e4d2a2e0c 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.28.0' +__version__ = '4.29.0' From 8876319660757aaedf0ae3e706be5fc44d3352d9 Mon Sep 17 00:00:00 2001 From: _run Date: Mon, 1 Sep 2025 17:46:44 +0400 Subject: [PATCH 477/480] Fix urgent suggested_post_parameters presence in sendmediagroup --- telebot/async_telebot.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 81cdc955d..192d9d369 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -5148,8 +5148,7 @@ async def send_media_group( business_connection_id: Optional[str]=None, message_effect_id: Optional[str]=None, allow_paid_broadcast: Optional[bool]=None, - direct_messages_topic_id: Optional[int]=None, - suggested_post_parameters: Optional[types.SuggestedPostParameters]=None) -> List[types.Message]: + direct_messages_topic_id: Optional[int]=None) -> List[types.Message]: """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. @@ -5197,11 +5196,6 @@ async def send_media_group( required if the message is sent to a direct messages chat :type direct_messages_topic_id: :obj:`int` - :param suggested_post_parameters: A JSON-serialized object containing the parameters of the suggested post to send; - for direct messages chats only. If the message is sent as a reply to another suggested post, then that suggested post - is automatically declined. - :type suggested_post_parameters: :class:`telebot.types.SuggestedPostParameters` - :return: On success, an array of Messages that were sent is returned. :rtype: List[types.Message] """ @@ -5236,8 +5230,7 @@ async def send_media_group( result = await asyncio_helper.send_media_group( self.token, chat_id, media, disable_notification, timeout, protect_content, message_thread_id, reply_parameters, business_connection_id, message_effect_id=message_effect_id, - allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id, - suggested_post_parameters=suggested_post_parameters) + allow_paid_broadcast=allow_paid_broadcast, direct_messages_topic_id=direct_messages_topic_id) return [types.Message.de_json(msg) for msg in result] async def send_location( From bf351eeb05b37fde11e5baf4a666c38292ea512a Mon Sep 17 00:00:00 2001 From: All-The-Foxes <116322192+All-The-Foxes@users.noreply.github.com> Date: Mon, 1 Sep 2025 15:13:40 -0400 Subject: [PATCH 478/480] Fix indentation error in init --- telebot/__init__.py | 720 ++++++++++++++++++++++---------------------- 1 file changed, 360 insertions(+), 360 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 59a8d7db8..368b531d4 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -46,7 +46,7 @@ REPLY_MARKUP_TYPES = Union[ - types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup, + types.InlineKeyboardMarkup, types.ReplyKeyboardMarkup, types.ReplyKeyboardRemove, types.ForceReply] @@ -93,7 +93,7 @@ class TeleBot: from telebot import TeleBot bot = TeleBot('token') # get token from @BotFather - # now you can register other handlers/update listeners, + # now you can register other handlers/update listeners, # and use bot methods. See more examples in examples/ directory: @@ -139,7 +139,7 @@ class TeleBot: :param use_class_middlewares: Use class middlewares, defaults to False :type use_class_middlewares: :obj:`bool`, optional - + :param disable_web_page_preview: Default value for disable_web_page_preview, defaults to None :type disable_web_page_preview: :obj:`bool`, optional @@ -151,7 +151,7 @@ class TeleBot: :param allow_sending_without_reply: Default value for allow_sending_without_reply, defaults to None :type allow_sending_without_reply: :obj:`bool`, optional - + :param colorful_logs: Outputs colorful logs :type colorful_logs: :obj:`bool`, optional @@ -168,7 +168,7 @@ def __init__( next_step_backend: Optional[HandlerBackend]=None, reply_backend: Optional[HandlerBackend]=None, exception_handler: Optional[ExceptionHandler]=None, last_update_id: Optional[int]=0, suppress_middleware_excepions: Optional[bool]=False, state_storage: Optional[StateStorageBase]=StateMemoryStorage(), - use_class_middlewares: Optional[bool]=False, + use_class_middlewares: Optional[bool]=False, disable_web_page_preview: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, @@ -194,7 +194,7 @@ def __init__( if validate_token: util.validate_token(self.token) - + self.bot_id: Union[int, None] = util.extract_bot_id(self.token) # subject to change in future, unspecified # logs-related @@ -292,7 +292,7 @@ def __init__( self.threaded = threaded if self.threaded: self.worker_pool = util.ThreadPool(self, num_threads=num_threads) - + @property def user(self) -> types.User: """ @@ -438,15 +438,15 @@ def set_webhook(self, url: Optional[str]=None, certificate: Optional[Union[str, Defaults to 40. Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput, defaults to None :type max_connections: :obj:`int`, optional - + :param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - + Please note that this parameter doesn't affect updates created before the call to the setWebhook, so unwanted updates may be received for a short period of time. Defaults to None - + :type allowed_updates: :obj:`list`, optional :param ip_address: The fixed IP address which will be used to send webhook requests instead of the IP address @@ -516,7 +516,7 @@ def run_webhooks(self, :type max_connections: :obj:`int`, optional :param allowed_updates: A JSON-serialized list of the update types you want your bot to receive. For example, specify [“message”, “edited_channel_post”, “callback_query”] - to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). + to only receive updates of these types. See Update for a complete list of available update types. Specify an empty list to receive all updates regardless of type (default). If not specified, the previous setting will be used. defaults to None :type allowed_updates: :obj:`list`, optional @@ -545,7 +545,7 @@ def run_webhooks(self, if not url_path: url_path = self.token + '/' if url_path[-1] != '/': url_path += '/' - + protocol = "https" if certificate else "http" if not webhook_url: webhook_url = "{}://{}:{}/{}".format(protocol, listen, port, url_path) @@ -627,8 +627,8 @@ def remove_webhook(self) -> bool: return self.set_webhook() # No params resets webhook - def get_updates(self, offset: Optional[int]=None, limit: Optional[int]=None, - timeout: Optional[int]=20, allowed_updates: Optional[List[str]]=None, + def get_updates(self, offset: Optional[int]=None, limit: Optional[int]=None, + timeout: Optional[int]=20, allowed_updates: Optional[List[str]]=None, long_polling_timeout: int=20) -> List[types.Update]: """ Use this method to receive incoming updates using long polling (wiki). An Array of Update objects is returned. @@ -678,14 +678,14 @@ def __retrieve_updates(self, timeout=20, long_polling_timeout=20, allowed_update Registered listeners and applicable message handlers will be notified when a new message arrives. :meta private: - + :raises ApiException when a call has failed. """ if self.skip_pending: self.__skip_updates() logger.debug('Skipped all pending messages') self.skip_pending = False - updates = self.get_updates(offset=(self.last_update_id + 1), + updates = self.get_updates(offset=(self.last_update_id + 1), allowed_updates=allowed_updates, timeout=timeout, long_polling_timeout=long_polling_timeout) self.process_new_updates(updates) @@ -726,7 +726,7 @@ def process_new_updates(self, updates: List[types.Update]): new_edited_business_messages = None new_deleted_business_messages = None new_purchased_paid_media = None - + for update in updates: if apihelper.ENABLE_MIDDLEWARE and not self.use_class_middlewares: try: @@ -810,7 +810,7 @@ def process_new_updates(self, updates: List[types.Update]): if update.purchased_paid_media: if new_purchased_paid_media is None: new_purchased_paid_media = [] new_purchased_paid_media.append(update.purchased_paid_media) - + if new_messages: self.process_new_messages(new_messages) if new_edited_messages: @@ -890,7 +890,7 @@ def process_new_message_reaction(self, new_message_reactions): :meta private: """ self._notify_command_handlers(self.message_reaction_handlers, new_message_reactions, 'message_reaction') - + def process_new_message_reaction_count(self, new_message_reaction_counts): """ :meta private: @@ -938,7 +938,7 @@ def process_new_poll_answer(self, new_poll_answers): :meta private: """ self._notify_command_handlers(self.poll_answer_handlers, new_poll_answers, 'poll_answer') - + def process_new_my_chat_member(self, new_my_chat_members): """ :meta private: @@ -986,13 +986,13 @@ def process_new_edited_business_message(self, new_edited_business_messages): :meta private: """ self._notify_command_handlers(self.edited_business_message_handlers, new_edited_business_messages, 'edited_business_message') - + def process_new_deleted_business_messages(self, new_deleted_business_messages): """ :meta private: """ self._notify_command_handlers(self.deleted_business_messages_handlers, new_deleted_business_messages, 'deleted_business_messages') - + def process_new_purchased_paid_media(self, new_purchased_paid_media): """ :meta private: @@ -1047,7 +1047,7 @@ def _setup_change_detector(self, path_to_watch: str): # Make it possible to specify --path argument to the script path = sys.argv[sys.argv.index('--path') + 1] if '--path' in sys.argv else '.' - + self.event_observer = Observer() self.event_observer.schedule(self.event_handler, path, recursive=True) self.event_observer.start() @@ -1066,7 +1066,7 @@ def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[boo Wrap polling with infinite loop and exception handling to avoid bot stops polling. .. note:: - + Install watchdog and psutil before using restart_on_change option. :param timeout: Request connection timeout. @@ -1083,11 +1083,11 @@ def infinity_polling(self, timeout: Optional[int]=20, skip_pending: Optional[boo :type logger_level: :obj:`int`. :param allowed_updates: A list of the update types you want your bot to receive. - For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. - See util.update_types for a complete list of available update types. - Specify an empty list to receive all update types except chat_member (default). + For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. + See util.update_types for a complete list of available update types. + Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - Please note that this parameter doesn't affect updates created before the call to the get_updates, + Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` @@ -1132,14 +1132,14 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F This allows the bot to retrieve Updates automatically and notify listeners and message handlers accordingly. Warning: Do not call this function more than once! - + Always gets updates. .. deprecated:: 4.1.1 Use :meth:`infinity_polling` instead. .. note:: - + Install watchdog and psutil before using restart_on_change option. :param interval: Delay between two update retrivals @@ -1153,7 +1153,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F :param skip_pending: skip old updates :type skip_pending: :obj:`bool` - + :param long_polling_timeout: Timeout in seconds for long polling (see API docs) :type long_polling_timeout: :obj:`int` @@ -1162,12 +1162,12 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F :type logger_level: :obj:`int` :param allowed_updates: A list of the update types you want your bot to receive. - For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. - See util.update_types for a complete list of available update types. - Specify an empty list to receive all update types except chat_member (default). + For example, specify [“message”, “edited_channel_post”, “callback_query”] to only receive updates of these types. + See util.update_types for a complete list of available update types. + Specify an empty list to receive all update types except chat_member (default). If not specified, the previous setting will be used. - - Please note that this parameter doesn't affect updates created before the call to the get_updates, + + Please note that this parameter doesn't affect updates created before the call to the get_updates, so unwanted updates may be received for a short period of time. :type allowed_updates: :obj:`list` of :obj:`str` @@ -1179,7 +1179,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F :param path_to_watch: Path to watch for changes. Defaults to None :type path_to_watch: :obj:`str` - + :return: """ if none_stop is not None: @@ -1193,7 +1193,7 @@ def polling(self, non_stop: Optional[bool]=False, skip_pending: Optional[bool]=F self._setup_change_detector(path_to_watch) logger.info('Starting your bot with username: [@%s]', self.user.username) - + if self.threaded: self.__threaded_polling(non_stop=non_stop, interval=interval, timeout=timeout, long_polling_timeout=long_polling_timeout, logger_level=logger_level, allowed_updates=allowed_updates) @@ -1386,9 +1386,9 @@ def get_me(self) -> types.User: def get_file(self, file_id: Optional[str]) -> types.File: """ Use this method to get basic info about a file and prepare it for downloading. - For the moment, bots can download files of up to 20MB in size. - On success, a File object is returned. - It is guaranteed that the link will be valid for at least 1 hour. + For the moment, bots can download files of up to 20MB in size. + On success, a File object is returned. + It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can be requested by calling get_file again. Telegram documentation: https://core.telegram.org/bots/api#getfile @@ -1431,11 +1431,11 @@ def download_file(self, file_path: str) -> bytes: def log_out(self) -> bool: """ - Use this method to log out from the cloud Bot API server before launching the bot locally. + Use this method to log out from the cloud Bot API server before launching the bot locally. You MUST log out the bot before running it locally, otherwise there is no guarantee that the bot will receive updates. - After a successful call, you can immediately log in on a local server, - but will not be able to log in back to the cloud Bot API server for 10 minutes. + After a successful call, you can immediately log in on a local server, + but will not be able to log in back to the cloud Bot API server for 10 minutes. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#logout @@ -1444,14 +1444,14 @@ def log_out(self) -> bool: :rtype: :obj:`bool` """ return apihelper.log_out(self.token) - - + + def close(self) -> bool: """ - Use this method to close the bot instance before moving it from one local server to another. + Use this method to close the bot instance before moving it from one local server to another. You need to delete the webhook before calling this method to ensure that the bot isn't launched again after server restart. - The method will return error 429 in the first 10 minutes after the bot is launched. + The method will return error 429 in the first 10 minutes after the bot is launched. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#close @@ -1459,10 +1459,10 @@ def close(self) -> bool: :return: :obj:`bool` """ return apihelper.close(self.token) - + def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reaction: Optional[List[types.ReactionType]]=None, is_big: Optional[bool]=None) -> bool: """ - Use this method to change the chosen reactions on a message. + 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. Returns True on success. @@ -1487,7 +1487,7 @@ def set_message_reaction(self, chat_id: Union[int, str], message_id: int, reacti self.token, chat_id, message_id, reaction = reaction, is_big = is_big) - def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, + def get_user_profile_photos(self, user_id: int, offset: Optional[int]=None, limit: Optional[int]=None) -> types.UserProfilePhotos: """ Use this method to get a list of profile pictures for a user. @@ -1531,7 +1531,7 @@ def set_user_emoji_status(self, user_id: int, emoji_status_custom_emoji_id: Opti """ return apihelper.set_user_emoji_status( self.token, user_id, emoji_status_custom_emoji_id=emoji_status_custom_emoji_id, emoji_status_expiration_date=emoji_status_expiration_date) - + def get_chat(self, chat_id: Union[int, str]) -> types.ChatFullInfo: """ @@ -1571,7 +1571,7 @@ def get_chat_administrators(self, chat_id: Union[int, str]) -> List[types.ChatMe On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. - Telegram documentation: https://core.telegram.org/bots/api#getchatadministrators + Telegram documentation: https://core.telegram.org/bots/api#getchatadministrators :param chat_id: Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) @@ -1623,7 +1623,7 @@ def set_chat_sticker_set(self, chat_id: Union[int, str], sticker_set_name: str) Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#setchatstickerset :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -1643,7 +1643,7 @@ def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in getChat requests to check if the bot can use this method. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletechatstickerset :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -1658,7 +1658,7 @@ def delete_chat_sticker_set(self, chat_id: Union[int, str]) -> bool: def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatMember: """ Use this method to get information about a member of a chat. Returns a ChatMember object on success. - + Telegram documentation: https://core.telegram.org/bots/api#getchatmember :param chat_id: Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) @@ -1676,11 +1676,11 @@ def get_chat_member(self, chat_id: Union[int, str], user_id: int) -> types.ChatM def send_message( - self, chat_id: Union[int, str], text: str, - parse_mode: Optional[str]=None, + self, chat_id: Union[int, str], text: str, + parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -1696,7 +1696,7 @@ def send_message( Use this method to send text messages. Warning: Do not send more than about 4096 characters each message, otherwise you'll risk an HTTP 414 error. - If you must send more than 4096 characters, + If you must send more than 4096 characters, use the `split_string` or `smart_split` function in util.py. Telegram documentation: https://core.telegram.org/bots/api#sendmessage @@ -1806,7 +1806,7 @@ def send_message( def forward_message( - self, chat_id: Union[int, str], from_chat_id: Union[int, str], + self, chat_id: Union[int, str], from_chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, timeout: Optional[int]=None, @@ -1855,13 +1855,13 @@ def forward_message( def copy_message( - self, chat_id: Union[int, str], - from_chat_id: Union[int, str], - message_id: int, - caption: Optional[str]=None, - parse_mode: Optional[str]=None, + self, chat_id: Union[int, str], + from_chat_id: Union[int, str], + message_id: int, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -1933,11 +1933,11 @@ def copy_message( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` - + :return: On success, the MessageId of the sent message is returned. :rtype: :class:`telebot.types.MessageID` """ - + disable_notification = self.disable_notification if (disable_notification is None) else disable_notification parse_mode = self.parse_mode if (parse_mode is None) else parse_mode protect_content = self.protect_content if (protect_content is None) else protect_content @@ -1969,7 +1969,7 @@ def copy_message( video_start_timestamp=video_start_timestamp)) - def delete_message(self, chat_id: Union[int, str], message_id: int, + def delete_message(self, chat_id: Union[int, str], message_id: int, timeout: Optional[int]=None) -> bool: """ Use this method to delete a message, including service messages, with the following limitations: @@ -1998,7 +1998,7 @@ def delete_message(self, chat_id: Union[int, str], message_id: int, """ return apihelper.delete_message(self.token, chat_id, message_id, timeout=timeout) - + def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ Use this method to delete multiple messages simultaneously. If some of the specified messages can't be found, they are skipped. @@ -2016,7 +2016,7 @@ def delete_messages(self, chat_id: Union[int, str], message_ids: List[int]): """ return apihelper.delete_messages(self.token, chat_id, message_ids) - + def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool]=None, message_thread_id: Optional[int]=None, protect_content: Optional[bool]=None) -> List[types.MessageID]: @@ -2058,7 +2058,7 @@ def forward_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, in protect_content=protect_content) return [types.MessageID.de_json(message_id) for message_id in result] - + def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], message_ids: List[int], disable_notification: Optional[bool] = None, message_thread_id: Optional[int] = None, protect_content: Optional[bool] = None, remove_caption: Optional[bool] = None) -> List[types.MessageID]: @@ -2103,7 +2103,7 @@ def copy_messages(self, chat_id: Union[str, int], from_chat_id: Union[str, int], self.token, chat_id, from_chat_id, message_ids, disable_notification=disable_notification, message_thread_id=message_thread_id, protect_content=protect_content, remove_caption=remove_caption) return [types.MessageID.de_json(message_id) for message_id in result] - + def send_checklist( self, business_connection_id: str, chat_id: Union[int, str], checklist: types.InputChecklist, @@ -2147,7 +2147,7 @@ def send_checklist( """ disable_notification = self.disable_notification if (disable_notification is None) else disable_notification protect_content = self.protect_content if (protect_content is None) else protect_content - + if reply_parameters and (reply_parameters.allow_sending_without_reply is None): reply_parameters.allow_sending_without_reply = self.allow_sending_without_reply @@ -2156,7 +2156,7 @@ def send_checklist( self.token, business_connection_id, chat_id, checklist, disable_notification=disable_notification, protect_content=protect_content, message_effect_id=message_effect_id, reply_parameters=reply_parameters, reply_markup=reply_markup)) - + def edit_message_checklist( self, business_connection_id: str, chat_id: Union[int, str], message_id: int, checklist: types.InputChecklist, @@ -2191,9 +2191,9 @@ def edit_message_checklist( def send_dice( self, chat_id: Union[int, str], - emoji: Optional[str]=None, disable_notification: Optional[bool]=None, + emoji: Optional[str]=None, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, @@ -2284,7 +2284,7 @@ def send_dice( def send_photo( - self, chat_id: Union[int, str], photo: Union[Any, str], + self, chat_id: Union[int, str], photo: Union[Any, str], caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, @@ -2304,7 +2304,7 @@ def send_photo( Use this method to send photos. On success, the sent Message is returned. Telegram documentation: https://core.telegram.org/bots/api#sendphoto - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2363,7 +2363,7 @@ def send_photo( :param allow_paid_broadcast: Pass True to allow up to 1000 messages per second, ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance :type allow_paid_broadcast: :obj:`bool` - + :return: On success, the sent Message is returned. :rtype: :class:`telebot.types.Message` """ @@ -2400,14 +2400,14 @@ def send_photo( def send_audio( - self, chat_id: Union[int, str], audio: Union[Any, str], - caption: Optional[str]=None, duration: Optional[int]=None, + self, chat_id: Union[int, str], audio: Union[Any, str], + caption: Optional[str]=None, duration: Optional[int]=None, performer: Optional[str]=None, title: Optional[str]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + parse_mode: Optional[str]=None, disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -2426,7 +2426,7 @@ def send_audio( For sending voice messages, use the send_voice method instead. Telegram documentation: https://core.telegram.org/bots/api#sendaudio - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2536,12 +2536,12 @@ def send_audio( def send_voice( - self, chat_id: Union[int, str], voice: Union[Any, str], - caption: Optional[str]=None, duration: Optional[int]=None, + self, chat_id: Union[int, str], voice: Union[Any, str], + caption: Optional[str]=None, duration: Optional[int]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, - disable_notification: Optional[bool]=None, + parse_mode: Optional[str]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -2555,7 +2555,7 @@ def send_voice( Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. Telegram documentation: https://core.telegram.org/bots/api#sendvoice - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2648,11 +2648,11 @@ def send_voice( def send_document( self, chat_id: Union[int, str], document: Union[Any, str], reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - caption: Optional[str]=None, + caption: Optional[str]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - parse_mode: Optional[str]=None, - disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + parse_mode: Optional[str]=None, + disable_notification: Optional[bool]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, caption_entities: Optional[List[types.MessageEntity]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility @@ -2669,7 +2669,7 @@ def send_document( Use this method to send general files. Telegram documentation: https://core.telegram.org/bots/api#senddocument - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -2883,7 +2883,7 @@ def send_sticker( if data and (not sticker): logger.warning('The parameter "data" is deprecated. Use "sticker" instead.') sticker = data - + return types.Message.de_json( apihelper.send_data( self.token, chat_id, sticker, 'sticker', @@ -2895,15 +2895,15 @@ def send_sticker( def send_video( - self, chat_id: Union[int, str], video: Union[Any, str], + self, chat_id: Union[int, str], video: Union[Any, str], duration: Optional[int]=None, width: Optional[int]=None, height: Optional[int]=None, - thumbnail: Optional[Union[Any, str]]=None, - caption: Optional[str]=None, - parse_mode: Optional[str]=None, + thumbnail: Optional[Union[Any, str]]=None, + caption: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, - supports_streaming: Optional[bool]=None, + supports_streaming: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility @@ -2923,7 +2923,7 @@ def send_video( start_timestamp: Optional[int]=None) -> types.Message: """ Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). - + Telegram documentation: https://core.telegram.org/bots/api#sendvideo :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -2953,7 +2953,7 @@ def send_video( :param start_timestamp: Start timestamp for the video in the message :type start_timestamp: :obj:`int` - + :param caption: Video caption (may also be used when resending videos by file_id), 0-1024 characters after entities parsing :type caption: :obj:`str` @@ -3061,19 +3061,19 @@ def send_video( def send_animation( - self, chat_id: Union[int, str], animation: Union[Any, str], + self, chat_id: Union[int, str], animation: Union[Any, str], duration: Optional[int]=None, width: Optional[int]=None, height: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, - caption: Optional[str]=None, + caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, message_thread_id: Optional[int]=None, has_spoiler: Optional[bool]=None, @@ -3086,7 +3086,7 @@ def send_animation( """ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent Message is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the future. - + Telegram documentation: https://core.telegram.org/bots/api#sendanimation :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -3104,7 +3104,7 @@ def send_animation( :param height: Animation height :type height: :obj:`int` - + :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, @@ -3206,13 +3206,13 @@ def send_animation( def send_video_note( - self, chat_id: Union[int, str], data: Union[Any, str], - duration: Optional[int]=None, + self, chat_id: Union[int, str], data: Union[Any, str], + duration: Optional[int]=None, length: Optional[int]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, - timeout: Optional[int]=None, + disable_notification: Optional[bool]=None, + timeout: Optional[int]=None, thumbnail: Optional[Union[Any, str]]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, @@ -3227,10 +3227,10 @@ def send_video_note( Use this method to send video messages. On success, the sent Message is returned. Telegram documentation: https://core.telegram.org/bots/api#sendvideonote - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - + :param data: Video note to send. Pass a file_id as String to send a video note that exists on the Telegram servers (recommended) or upload a new video using multipart/form-data. Sending video notes by a URL is currently unsupported :type data: :obj:`str` or :class:`telebot.types.InputFile` @@ -3261,7 +3261,7 @@ def send_video_note( :param thumbnail: Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, - so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . + so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . :type thumbnail: :obj:`str` or :class:`telebot.types.InputFile` :param protect_content: Protects the contents of the sent message from forwarding and saving @@ -3321,7 +3321,7 @@ def send_video_note( protect_content=protect_content, message_thread_id=message_thread_id, reply_parameters=reply_parameters, business_connection_id=business_connection_id, message_effect_id=message_effect_id, allow_paid_broadcast=allow_paid_broadcast) ) - + def send_paid_media( self, chat_id: Union[int, str], star_count: int, media: List[types.InputPaidMedia], caption: Optional[str]=None, parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, @@ -3392,11 +3392,11 @@ def send_paid_media( def send_media_group( - self, chat_id: Union[int, str], + self, chat_id: Union[int, str], media: List[Union[ - types.InputMediaAudio, types.InputMediaDocument, + types.InputMediaAudio, types.InputMediaDocument, types.InputMediaPhoto, types.InputMediaVideo]], - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, @@ -3409,7 +3409,7 @@ def send_media_group( """ Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can be only grouped in an album with messages of the same type. On success, an array of Messages that were sent is returned. - + Telegram documentation: https://core.telegram.org/bots/api#sendmediagroup :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -3487,17 +3487,17 @@ def send_media_group( def send_location( - self, chat_id: Union[int, str], - latitude: float, longitude: float, + self, chat_id: Union[int, str], + latitude: float, longitude: float, live_period: Optional[int]=None, - reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - disable_notification: Optional[bool]=None, + reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + disable_notification: Optional[bool]=None, timeout: Optional[int]=None, - horizontal_accuracy: Optional[float]=None, - heading: Optional[int]=None, + horizontal_accuracy: Optional[float]=None, + heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, - allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility + allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, reply_parameters: Optional[types.ReplyParameters]=None, @@ -3601,14 +3601,14 @@ def send_location( def edit_message_live_location( - self, latitude: float, longitude: float, - chat_id: Optional[Union[int, str]]=None, + self, latitude: float, longitude: float, + chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, - horizontal_accuracy: Optional[float]=None, - heading: Optional[int]=None, + horizontal_accuracy: Optional[float]=None, + heading: Optional[int]=None, proximity_alert_radius: Optional[int]=None, live_period: Optional[int]=None, business_connection_id: Optional[str]=None @@ -3669,9 +3669,9 @@ def edit_message_live_location( def stop_message_live_location( - self, chat_id: Optional[Union[int, str]]=None, + self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, timeout: Optional[int]=None, business_connection_id: Optional[str]=None) -> Union[types.Message, bool]: @@ -3680,7 +3680,7 @@ def stop_message_live_location( On success, if the message is not an inline message, the edited Message is returned, otherwise True is returned. Telegram documentation: https://core.telegram.org/bots/api#stopmessagelivelocation - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -3711,14 +3711,14 @@ def stop_message_live_location( def send_venue( - self, chat_id: Union[int, str], - latitude: Optional[float], longitude: Optional[float], - title: str, address: str, - foursquare_id: Optional[str]=None, + self, chat_id: Union[int, str], + latitude: Optional[float], longitude: Optional[float], + title: str, address: str, + foursquare_id: Optional[str]=None, foursquare_type: Optional[str]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility google_place_id: Optional[str]=None, @@ -3731,12 +3731,12 @@ def send_venue( allow_paid_broadcast: Optional[bool]=None) -> types.Message: """ Use this method to send information about a venue. On success, the sent Message is returned. - + Telegram documentation: https://core.telegram.org/bots/api#sendvenue :param chat_id: Unique identifier for the target chat or username of the target channel :type chat_id: :obj:`int` or :obj:`str` - + :param latitude: Latitude of the venue :type latitude: :obj:`float` @@ -3833,12 +3833,12 @@ def send_venue( def send_contact( - self, chat_id: Union[int, str], phone_number: str, - first_name: str, last_name: Optional[str]=None, + self, chat_id: Union[int, str], phone_number: str, + first_name: str, last_name: Optional[str]=None, vcard: Optional[str]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, message_thread_id: Optional[int]=None, @@ -3950,7 +3950,7 @@ def send_chat_action( :param chat_id: Unique identifier for the target chat or username of the target channel :type chat_id: :obj:`int` or :obj:`str` - + :param action: Type of action to broadcast. Choose one, depending on what the user is about to receive: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_voice or upload_voice for voice notes, upload_document for general files, @@ -3972,11 +3972,11 @@ def send_chat_action( return apihelper.send_chat_action( self.token, chat_id, action, timeout=timeout, message_thread_id=message_thread_id, business_connection_id=business_connection_id) - + @util.deprecated(deprecation_text="Use ban_chat_member instead") def kick_chat_member( - self, chat_id: Union[int, str], user_id: int, - until_date:Optional[Union[int, datetime]]=None, + self, chat_id: Union[int, str], user_id: int, + until_date:Optional[Union[int, datetime]]=None, revoke_messages: Optional[bool]=None) -> bool: """ This function is deprecated. Use `ban_chat_member` instead. @@ -3986,13 +3986,13 @@ def kick_chat_member( def ban_chat_member( - self, chat_id: Union[int, str], user_id: int, - until_date: Optional[Union[int, datetime]]=None, + self, chat_id: Union[int, str], user_id: int, + until_date: Optional[Union[int, datetime]]=None, revoke_messages: Optional[bool]=None) -> bool: """ - Use this method to ban a user in a group, a supergroup or a channel. - In the case of supergroups and channels, the user will not be able to return to the chat on their - own using invite links, etc., unless unbanned first. + Use this method to ban a user in a group, a supergroup or a channel. + In the case of supergroups and channels, the user will not be able to return to the chat on their + own using invite links, etc., unless unbanned first. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#banchatmember @@ -4009,10 +4009,10 @@ def ban_chat_member( :type until_date: :obj:`int` or :obj:`datetime` :param revoke_messages: Pass True to delete all messages from the chat for the user that is being removed. - If False, the user will be able to see messages in the group that were sent before the user was removed. + If False, the user will be able to see messages in the group that were sent before the user was removed. Always True for supergroups and channels. :type revoke_messages: :obj:`bool` - + :return: Returns True on success. :rtype: :obj:`bool` """ @@ -4021,7 +4021,7 @@ def ban_chat_member( def unban_chat_member( - self, chat_id: Union[int, str], user_id: int, + self, chat_id: Union[int, str], user_id: int, only_if_banned: Optional[bool]=False) -> bool: """ Use this method to unban a previously kicked user in a supergroup or channel. @@ -4049,15 +4049,15 @@ def unban_chat_member( def restrict_chat_member( - self, chat_id: Union[int, str], user_id: int, + self, chat_id: Union[int, str], user_id: int, until_date: Optional[Union[int, datetime]]=None, - can_send_messages: Optional[bool]=None, + can_send_messages: Optional[bool]=None, can_send_media_messages: Optional[bool]=None, - can_send_polls: Optional[bool]=None, + can_send_polls: Optional[bool]=None, can_send_other_messages: Optional[bool]=None, - can_add_web_page_previews: Optional[bool]=None, + can_add_web_page_previews: Optional[bool]=None, can_change_info: Optional[bool]=None, - can_invite_users: Optional[bool]=None, + can_invite_users: Optional[bool]=None, can_pin_messages: Optional[bool]=None, permissions: Optional[types.ChatPermissions]=None, use_independent_chat_permissions: Optional[bool]=None) -> bool: @@ -4085,10 +4085,10 @@ def restrict_chat_member( :param can_send_messages: deprecated :type can_send_messages: :obj:`bool` - + :param can_send_media_messages: deprecated :type can_send_media_messages: :obj:`bool` - + :param can_send_polls: deprecated :type can_send_polls: :obj:`bool` @@ -4139,16 +4139,16 @@ def restrict_chat_member( def promote_chat_member( self, chat_id: Union[int, str], user_id: int, - can_change_info: Optional[bool]=None, + can_change_info: Optional[bool]=None, can_post_messages: Optional[bool]=None, - can_edit_messages: Optional[bool]=None, - can_delete_messages: Optional[bool]=None, + can_edit_messages: Optional[bool]=None, + can_delete_messages: Optional[bool]=None, can_invite_users: Optional[bool]=None, - can_restrict_members: Optional[bool]=None, - can_pin_messages: Optional[bool]=None, + can_restrict_members: Optional[bool]=None, + can_pin_messages: Optional[bool]=None, can_promote_members: Optional[bool]=None, - is_anonymous: Optional[bool]=None, - can_manage_chat: Optional[bool]=None, + is_anonymous: Optional[bool]=None, + can_manage_chat: Optional[bool]=None, can_manage_video_chats: Optional[bool]=None, can_manage_voice_chats: Optional[bool]=None, can_manage_topics: Optional[bool]=None, @@ -4198,9 +4198,9 @@ def promote_chat_member( :param is_anonymous: Pass True, if the administrator's presence in the chat is hidden :type is_anonymous: :obj:`bool` - :param can_manage_chat: Pass True, if the administrator can access the chat event log, chat statistics, - message statistics in channels, see channel members, - see anonymous administrators in supergroups and ignore slow mode. + :param can_manage_chat: Pass True, if the administrator can access the chat event log, chat statistics, + message statistics in channels, see channel members, + see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege :type can_manage_chat: :obj:`bool` @@ -4267,14 +4267,14 @@ def set_chat_administrator_custom_title( """ return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title) - + def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ Use this method to ban a channel chat in a supergroup or a channel. - The owner of the chat will not be able to send messages and join live - streams on behalf of the chat, unless it is unbanned first. - The bot must be an administrator in the supergroup or channel - for this to work and must have the appropriate administrator rights. + The owner of the chat will not be able to send messages and join live + streams on behalf of the chat, unless it is unbanned first. + The bot must be an administrator in the supergroup or channel + for this to work and must have the appropriate administrator rights. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#banchatsenderchat @@ -4293,8 +4293,8 @@ def ban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[i def unban_chat_sender_chat(self, chat_id: Union[int, str], sender_chat_id: Union[int, str]) -> bool: """ - Use this method to unban a previously banned channel chat in a supergroup or channel. - The bot must be an administrator for this to work and must have the appropriate + Use this method to unban a previously banned channel chat in a supergroup or channel. + The bot must be an administrator for this to work and must have the appropriate administrator rights. Returns True on success. @@ -4345,7 +4345,7 @@ def set_chat_permissions( def create_chat_invite_link( self, chat_id: Union[int, str], name: Optional[str]=None, - expire_date: Optional[Union[int, datetime]]=None, + expire_date: Optional[Union[int, datetime]]=None, member_limit: Optional[int]=None, creates_join_request: Optional[bool]=None) -> types.ChatInviteLink: """ @@ -4432,7 +4432,7 @@ def create_chat_subscription_invite_link( :param chat_id: Unique identifier for the target channel chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - + :param name: Invite link name; 0-32 characters :type name: :obj:`str` @@ -4450,7 +4450,7 @@ def create_chat_subscription_invite_link( return types.ChatInviteLink.de_json( apihelper.create_chat_subscription_invite_link(self.token, chat_id, subscription_period, subscription_price, name=name) ) - + def edit_chat_subscription_invite_link( self, chat_id: Union[int, str], invite_link: str, name: Optional[str]=None) -> types.ChatInviteLink: """ @@ -4480,7 +4480,7 @@ def revoke_chat_invite_link( self, chat_id: Union[int, str], invite_link: str) -> types.ChatInviteLink: """ Use this method to revoke an invite link created by the bot. - Note: If the primary link is revoked, a new link is automatically generated The bot must be an administrator + Note: If the primary link is revoked, a new link is automatically generated The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Telegram documentation: https://core.telegram.org/bots/api#revokechatinvitelink @@ -4519,7 +4519,7 @@ def export_chat_invite_link(self, chat_id: Union[int, str]) -> str: def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ - Use this method to approve a chat join request. + Use this method to approve a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns True on success. @@ -4540,7 +4540,7 @@ def approve_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int def decline_chat_join_request(self, chat_id: Union[str, int], user_id: Union[int, str]) -> bool: """ - Use this method to decline a chat join request. + Use this method to decline a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns True on success. @@ -4599,21 +4599,21 @@ def delete_chat_photo(self, chat_id: Union[int, str]) -> bool: """ return apihelper.delete_chat_photo(self.token, chat_id) - - def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, + + def get_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> List[types.BotCommand]: """ - Use this method to get the current list of the bot's commands. + Use this method to get the current list of the bot's commands. Returns List of BotCommand on success. Telegram documentation: https://core.telegram.org/bots/api#getmycommands - :param scope: The scope of users for which the commands are relevant. + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -4641,7 +4641,7 @@ def set_my_name(self, name: Optional[str]=None, language_code: Optional[str]=Non """ return apihelper.set_my_name(self.token, name=name, language_code=language_code) - + def get_my_name(self, language_code: Optional[str]=None): """ Use this method to get the current bot name for the given user language. @@ -4680,7 +4680,7 @@ def set_my_description(self, description: Optional[str]=None, language_code: Opt return apihelper.set_my_description( self.token, description=description, language_code=language_code) - + def get_my_description(self, language_code: Optional[str]=None): """ Use this method to get the current bot description for the given user language. @@ -4696,11 +4696,11 @@ def get_my_description(self, language_code: Optional[str]=None): return types.BotDescription.de_json( apihelper.get_my_description(self.token, language_code=language_code)) - + def set_my_short_description(self, short_description:Optional[str]=None, language_code:Optional[str]=None): """ Use this method to change the bot's short description, which is shown on the bot's profile page and - is sent together with the link when users share the bot. + is sent together with the link when users share the bot. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmyshortdescription @@ -4717,7 +4717,7 @@ def set_my_short_description(self, short_description:Optional[str]=None, languag return apihelper.set_my_short_description( self.token, short_description=short_description, language_code=language_code) - + def get_my_short_description(self, language_code: Optional[str]=None): """ Use this method to get the current bot short description for the given user language. @@ -4736,13 +4736,13 @@ def get_my_short_description(self, language_code: Optional[str]=None): def set_chat_menu_button(self, chat_id: Union[int, str]=None, menu_button: types.MenuButton=None) -> bool: """ - Use this method to change the bot's menu button in a private chat, - or the default menu button. + Use this method to change the bot's menu button in a private chat, + or the default menu button. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setchatmenubutton - :param chat_id: Unique identifier for the target private chat. + :param chat_id: Unique identifier for the target private chat. If not specified, default bot's menu button will be changed. :type chat_id: :obj:`int` or :obj:`str` @@ -4774,13 +4774,13 @@ def get_chat_menu_button(self, chat_id: Union[int, str]=None) -> types.MenuButto apihelper.get_chat_menu_button(self.token, chat_id=chat_id)) - def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, + def set_my_default_administrator_rights(self, rights: types.ChatAdministratorRights=None, for_channels: Optional[bool]=None) -> bool: """ Use this method to change the default administrator rights requested by the bot when it's added as an administrator to groups or channels. These rights will be suggested to users, but they are are free to modify - the list before adding the bot. + the list before adding the bot. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setmydefaultadministratorrights @@ -4834,8 +4834,8 @@ def get_business_connection(self, business_connection_id: str) -> types.Business return types.BusinessConnection.de_json( apihelper.get_business_connection(self.token, business_connection_id) ) - - + + def set_my_commands(self, commands: List[types.BotCommand], scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> bool: @@ -4847,12 +4847,12 @@ def set_my_commands(self, commands: List[types.BotCommand], :param commands: List of BotCommand. At most 100 commands can be specified. :type commands: :obj:`list` of :class:`telebot.types.BotCommand` - :param scope: The scope of users for which the commands are relevant. + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -4861,22 +4861,22 @@ def set_my_commands(self, commands: List[types.BotCommand], """ return apihelper.set_my_commands(self.token, commands, scope=scope, language_code=language_code) - - def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, + + def delete_my_commands(self, scope: Optional[types.BotCommandScope]=None, language_code: Optional[str]=None) -> bool: """ - Use this method to delete the list of the bot's commands for the given scope and user language. - After deletion, higher level commands will be shown to affected users. + Use this method to delete the list of the bot's commands for the given scope and user language. + After deletion, higher level commands will be shown to affected users. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#deletemycommands - - :param scope: The scope of users for which the commands are relevant. + + :param scope: The scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. :type scope: :class:`telebot.types.BotCommandScope` - :param language_code: A two-letter ISO 639-1 language code. If empty, - commands will be applied to all users from the given scope, + :param language_code: A two-letter ISO 639-1 language code. If empty, + commands will be applied to all users from the given scope, for whose language there are no dedicated commands :type language_code: :obj:`str` @@ -4930,7 +4930,7 @@ def set_chat_description(self, chat_id: Union[int, str], description: Optional[s def pin_chat_message( - self, chat_id: Union[int, str], message_id: int, + self, chat_id: Union[int, str], message_id: int, disable_notification: Optional[bool]=False, business_connection_id: Optional[str]=None) -> bool: """ Use this method to pin a message in a supergroup. @@ -5005,10 +5005,10 @@ def unpin_all_chat_messages(self, chat_id: Union[int, str]) -> bool: def edit_message_text( - self, text: str, - chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + self, text: str, + chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, + inline_message_id: Optional[str]=None, parse_mode: Optional[str]=None, entities: Optional[List[types.MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, # deprecated, for backward compatibility @@ -5058,7 +5058,7 @@ def edit_message_text( :rtype: :obj:`types.Message` or :obj:`bool` """ parse_mode = self.parse_mode if (parse_mode is None) else parse_mode - + if disable_web_page_preview is not None: # show a deprecation warning logger.warning("The parameter 'disable_web_page_preview' is deprecated. Use 'link_preview_options' instead.") @@ -5089,9 +5089,9 @@ def edit_message_text( def edit_message_media( - self, media: Any, chat_id: Optional[Union[int, str]]=None, + self, media: Any, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: @@ -5100,7 +5100,7 @@ def edit_message_media( If a message is part of a message album, then it can be edited only to an audio for audio albums, only to a document for document albums and to a photo or a video otherwise. When an inline message is edited, a new file can't be uploaded; use a previously uploaded file via its file_id or specify a URL. On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. - Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. + Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within 48 hours from the time they were sent. Telegram documentation: https://core.telegram.org/bots/api#editmessagemedia @@ -5109,7 +5109,7 @@ def edit_message_media( :param chat_id: Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` - :param message_id: Required if inline_message_id is not specified. Identifier of the sent message + :param message_id: Required if inline_message_id is not specified. Identifier of the sent message :type message_id: :obj:`int` :param inline_message_id: Required if chat_id and message_id are not specified. Identifier of the inline message @@ -5137,9 +5137,9 @@ def edit_message_media( def edit_message_reply_markup( - self, chat_id: Optional[Union[int, str]]=None, + self, chat_id: Optional[Union[int, str]]=None, message_id: Optional[int]=None, - inline_message_id: Optional[str]=None, + inline_message_id: Optional[str]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None, timeout: Optional[int]=None) -> Union[types.Message, bool]: @@ -5179,10 +5179,10 @@ def edit_message_reply_markup( def send_game( - self, chat_id: Union[int, str], game_short_name: str, + self, chat_id: Union[int, str], game_short_name: str, disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility protect_content: Optional[bool]=None, @@ -5273,10 +5273,10 @@ def send_game( def set_game_score( - self, user_id: Union[int, str], score: int, - force: Optional[bool]=None, - chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + self, user_id: Union[int, str], score: int, + force: Optional[bool]=None, + chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None, disable_edit_message: Optional[bool]=None) -> Union[types.Message, bool]: """ @@ -5319,7 +5319,7 @@ def set_game_score( def get_game_high_scores( self, user_id: int, chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None) -> List[types.GameHighScore]: """ Use this method to get data for high score tables. Will return the score of the specified user and several of @@ -5352,20 +5352,20 @@ def get_game_high_scores( def send_invoice( - self, chat_id: Union[int, str], title: str, description: str, - invoice_payload: str, provider_token: Union[str, None], currency: str, - prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, - photo_url: Optional[str]=None, photo_size: Optional[int]=None, + self, chat_id: Union[int, str], title: str, description: str, + invoice_payload: str, provider_token: Union[str, None], currency: str, + prices: List[types.LabeledPrice], start_parameter: Optional[str]=None, + photo_url: Optional[str]=None, photo_size: Optional[int]=None, photo_width: Optional[int]=None, photo_height: Optional[int]=None, - need_name: Optional[bool]=None, need_phone_number: Optional[bool]=None, + need_name: Optional[bool]=None, need_phone_number: Optional[bool]=None, need_email: Optional[bool]=None, need_shipping_address: Optional[bool]=None, - send_phone_number_to_provider: Optional[bool]=None, - send_email_to_provider: Optional[bool]=None, + send_phone_number_to_provider: Optional[bool]=None, + send_email_to_provider: Optional[bool]=None, is_flexible: Optional[bool]=None, - disable_notification: Optional[bool]=None, + disable_notification: Optional[bool]=None, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, - provider_data: Optional[str]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + provider_data: Optional[str]=None, timeout: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility max_tip_amount: Optional[int] = None, @@ -5416,7 +5416,7 @@ def send_invoice( :param photo_size: Photo size in bytes :type photo_size: :obj:`int` - :param photo_width: Photo width + :param photo_width: Photo width :type photo_width: :obj:`int` :param photo_height: Photo height @@ -5530,9 +5530,9 @@ def send_invoice( ) def create_invoice_link(self, - title: str, description: str, payload:str, provider_token: Union[str, None], + title: str, description: str, payload:str, provider_token: Union[str, None], currency: str, prices: List[types.LabeledPrice], - max_tip_amount: Optional[int] = None, + max_tip_amount: Optional[int] = None, suggested_tip_amounts: Optional[List[int]]=None, provider_data: Optional[str]=None, photo_url: Optional[str]=None, @@ -5548,9 +5548,9 @@ def create_invoice_link(self, is_flexible: Optional[bool]=None, subscription_period: Optional[int]=None, business_connection_id: Optional[str]=None) -> str: - + """ - Use this method to create a link for an invoice. + Use this method to create a link for an invoice. Returns the created invoice link as String on success. Telegram documentation: @@ -5649,17 +5649,17 @@ def create_invoice_link(self, # noinspection PyShadowingBuiltins def send_poll( self, chat_id: Union[int, str], question: str, options: List[Union[str, types.InputPollOption]], - is_anonymous: Optional[bool]=None, type: Optional[str]=None, - allows_multiple_answers: Optional[bool]=None, + is_anonymous: Optional[bool]=None, type: Optional[str]=None, + allows_multiple_answers: Optional[bool]=None, correct_option_id: Optional[int]=None, - explanation: Optional[str]=None, - explanation_parse_mode: Optional[str]=None, - open_period: Optional[int]=None, - close_date: Optional[Union[int, datetime]]=None, + explanation: Optional[str]=None, + explanation_parse_mode: Optional[str]=None, + open_period: Optional[int]=None, + close_date: Optional[Union[int, datetime]]=None, is_closed: Optional[bool]=None, disable_notification: Optional[bool]=False, reply_to_message_id: Optional[int]=None, # deprecated, for backward compatibility - reply_markup: Optional[REPLY_MARKUP_TYPES]=None, + reply_markup: Optional[REPLY_MARKUP_TYPES]=None, allow_sending_without_reply: Optional[bool]=None, # deprecated, for backward compatibility timeout: Optional[int]=None, explanation_entities: Optional[List[types.MessageEntity]]=None, @@ -5816,7 +5816,7 @@ def send_poll( def stop_poll( - self, chat_id: Union[int, str], message_id: int, + self, chat_id: Union[int, str], message_id: int, reply_markup: Optional[types.InlineKeyboardMarkup]=None, business_connection_id: Optional[str]=None) -> types.Poll: """ @@ -5845,8 +5845,8 @@ def stop_poll( def answer_shipping_query( - self, shipping_query_id: str, ok: bool, - shipping_options: Optional[List[types.ShippingOption]]=None, + self, shipping_query_id: str, ok: bool, + shipping_options: Optional[List[types.ShippingOption]]=None, error_message: Optional[str]=None) -> bool: """ Asks for an answer to a shipping question. @@ -5874,7 +5874,7 @@ def answer_shipping_query( def answer_pre_checkout_query( - self, pre_checkout_query_id: str, ok: bool, + self, pre_checkout_query_id: str, ok: bool, error_message: Optional[str]=None) -> bool: """ Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form of an Update with the @@ -5886,7 +5886,7 @@ def answer_pre_checkout_query( Telegram documentation: https://core.telegram.org/bots/api#answerprecheckoutquery - :param pre_checkout_query_id: Unique identifier for the query to be answered + :param pre_checkout_query_id: Unique identifier for the query to be answered :type pre_checkout_query_id: :obj:`int` :param ok: Specify True if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. Use False if there are any problems. @@ -5902,11 +5902,11 @@ def answer_pre_checkout_query( """ return apihelper.answer_pre_checkout_query( self.token, pre_checkout_query_id, ok, error_message=error_message) - + def get_my_star_balance(self) -> types.StarAmount: """ Returns the bot's current Telegram Stars balance. On success, returns a StarAmount object. - + Telegram documentation: https://core.telegram.org/bots/api#getmystarbalance :return: On success, returns a StarAmount object. @@ -5933,8 +5933,8 @@ def get_star_transactions(self, offset: Optional[int]=None, limit: Optional[int] return types.StarTransactions.de_json( apihelper.get_star_transactions(self.token, offset=offset, limit=limit) ) - - + + def refund_star_payment(self, user_id: int, telegram_payment_charge_id: str) -> bool: """ Refunds a successful payment in Telegram Stars. Returns True on success. @@ -5973,10 +5973,10 @@ def edit_user_star_subscription(self, user_id: int, telegram_payment_charge_id: return apihelper.edit_user_star_subscription(self.token, user_id, telegram_payment_charge_id, is_canceled) def edit_message_caption( - self, caption: str, chat_id: Optional[Union[int, str]]=None, - message_id: Optional[int]=None, + self, caption: str, chat_id: Optional[Union[int, str]]=None, + message_id: Optional[int]=None, inline_message_id: Optional[str]=None, - parse_mode: Optional[str]=None, + parse_mode: Optional[str]=None, caption_entities: Optional[List[types.MessageEntity]]=None, reply_markup: Optional[types.InlineKeyboardMarkup]=None, show_caption_above_media: Optional[bool]=None, @@ -6068,12 +6068,12 @@ def reply_to(self, message: types.Message, text: str, **kwargs) -> types.Message def answer_inline_query( - self, inline_query_id: str, - results: List[Any], - cache_time: Optional[int]=None, - is_personal: Optional[bool]=None, + self, inline_query_id: str, + results: List[Any], + cache_time: Optional[int]=None, + is_personal: Optional[bool]=None, next_offset: Optional[str]=None, - switch_pm_text: Optional[str]=None, + switch_pm_text: Optional[str]=None, switch_pm_parameter: Optional[str]=None, button: Optional[types.InlineQueryResultsButton]=None) -> bool: """ @@ -6120,7 +6120,7 @@ def answer_inline_query( if not button and (switch_pm_text or switch_pm_parameter): logger.warning("switch_pm_text and switch_pm_parameter are deprecated for answer_inline_query. Use button instead.") button = types.InlineQueryResultsButton(text=switch_pm_text, start_parameter=switch_pm_parameter) - + return apihelper.answer_inline_query( self.token, inline_query_id, results, cache_time=cache_time, is_personal=is_personal, next_offset=next_offset, button=button) @@ -6128,7 +6128,7 @@ def answer_inline_query( def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bool: """ - Use this method to clear the list of pinned messages in a General forum topic. + Use this method to clear the list of pinned messages in a General forum topic. The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator right in the supergroup. Returns True on success. @@ -6145,8 +6145,8 @@ def unpin_all_general_forum_topic_messages(self, chat_id: Union[int, str]) -> bo def answer_callback_query( - self, callback_query_id: int, - text: Optional[str]=None, show_alert: Optional[bool]=None, + self, callback_query_id: int, + text: Optional[str]=None, show_alert: Optional[bool]=None, url: Optional[str]=None, cache_time: Optional[int]=None) -> bool: """ Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to @@ -6176,7 +6176,7 @@ def answer_callback_query( return apihelper.answer_callback_query( self.token, callback_query_id, text=text, show_alert=show_alert, url=url, cache_time=cache_time) - + def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types.UserChatBoosts: """ Use this method to get the list of boosts added to a chat by a user. Requires administrator rights in the chat. Returns a UserChatBoosts object. @@ -6199,7 +6199,7 @@ def get_user_chat_boosts(self, chat_id: Union[int, str], user_id: int) -> types. # noinspection PyShadowingBuiltins def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[Any, str]=None, format: Optional[str]=None) -> bool: """ - Use this method to set the thumbnail of a sticker set. + Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumbnail @@ -6230,11 +6230,11 @@ def set_sticker_set_thumbnail(self, name: str, user_id: int, thumbnail: Union[An return apihelper.set_sticker_set_thumbnail(self.token, name, user_id, thumbnail, format) - + @util.deprecated(deprecation_text="Use set_sticker_set_thumbnail instead") def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]=None): """ - Use this method to set the thumbnail of a sticker set. + Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns True on success. Telegram documentation: https://core.telegram.org/bots/api#setstickersetthumb @@ -6258,7 +6258,7 @@ def set_sticker_set_thumb(self, name: str, user_id: int, thumb: Union[Any, str]= def get_sticker_set(self, name: str) -> types.StickerSet: """ Use this method to get a sticker set. On success, a StickerSet object is returned. - + Telegram documentation: https://core.telegram.org/bots/api#getstickerset :param name: Sticker set name @@ -6285,7 +6285,7 @@ def get_custom_emoji_stickers(self, custom_emoji_ids: List[str]) -> List[types.S result = apihelper.get_custom_emoji_stickers(self.token, custom_emoji_ids) return [types.Sticker.de_json(sticker) for sticker in result] - + def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: """ Use this method to change search keywords assigned to a regular or custom emoji sticker. @@ -6303,7 +6303,7 @@ def set_sticker_keywords(self, sticker: str, keywords: List[str]=None) -> bool: """ return apihelper.set_sticker_keywords(self.token, sticker, keywords=keywords) - + def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosition=None) -> bool: """ Use this method to change the mask position of a mask sticker. @@ -6320,7 +6320,7 @@ def set_sticker_mask_position(self, sticker: str, mask_position: types.MaskPosit :rtype: :obj:`bool` """ return apihelper.set_sticker_mask_position(self.token, sticker, mask_position=mask_position) - + def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Optional[str]=None) -> bool: """ @@ -6338,7 +6338,7 @@ def set_custom_emoji_sticker_set_thumbnail(self, name: str, custom_emoji_id: Opt """ return apihelper.set_custom_emoji_sticker_set_thumbnail(self.token, name, custom_emoji_id=custom_emoji_id) - + def set_sticker_set_title(self, name: str, title: str) -> bool: """ Use this method to set the title of a created sticker set. @@ -6355,7 +6355,7 @@ def set_sticker_set_title(self, name: str, title: str) -> bool: """ return apihelper.set_sticker_set_title(self.token, name, title) - + def delete_sticker_set(self, name:str) -> bool: """ Use this method to delete a sticker set. Returns True on success. @@ -6368,7 +6368,7 @@ def delete_sticker_set(self, name:str) -> bool: """ return apihelper.delete_sticker_set(self.token, name) - def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, + def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None, text: Optional[str]=None, text_parse_mode: Optional[str]=None, text_entities: Optional[List[types.MessageEntity]]=None, pay_for_upgrade: Optional[bool]=None, chat_id: Optional[Union[str, int]] = None) -> bool: """ @@ -6403,13 +6403,13 @@ def send_gift(self, user_id: Optional[Union[str, int]] = None, gift_id: str=None """ if user_id is None and chat_id is None: raise ValueError("Either user_id or chat_id must be specified.") - + if gift_id is None: raise ValueError("gift_id must be specified.") - + return apihelper.send_gift(self.token, gift_id, text=text, text_parse_mode=text_parse_mode, text_entities=text_entities, pay_for_upgrade=pay_for_upgrade, chat_id=chat_id, user_id=user_id) - + def verify_user(self, user_id: int, custom_description: Optional[str]=None) -> bool: """ Verifies a user on behalf of the organization which is represented by the bot. Returns True on success. @@ -6585,12 +6585,12 @@ def set_business_account_gift_settings( :rtype: :obj:`bool` """ return apihelper.set_business_account_gift_settings(self.token, business_connection_id, show_gift_button, accepted_gift_types) - + def get_business_account_star_balance(self, business_connection_id: str) -> types.StarAmount: """ Returns the amount of Telegram Stars owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns StarAmount on success. - + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountstarbalance :param business_connection_id: Unique identifier of the business connection @@ -6602,7 +6602,7 @@ def get_business_account_star_balance(self, business_connection_id: str) -> type return types.StarAmount.de_json( apihelper.get_business_account_star_balance(self.token, business_connection_id) ) - + def transfer_business_account_stars(self, business_connection_id: str, star_count: int) -> bool: """ Transfers Telegram Stars from the business account balance to the bot's balance. Requires the can_transfer_stars business bot right. Returns True on success. @@ -6619,7 +6619,7 @@ def transfer_business_account_stars(self, business_connection_id: str, star_coun :rtype: :obj:`bool` """ return apihelper.transfer_business_account_stars(self.token, business_connection_id, star_count) - + def get_business_account_gifts( self, business_connection_id: str, exclude_unsaved: Optional[bool]=None, @@ -6632,7 +6632,7 @@ def get_business_account_gifts( limit: Optional[int]=None) -> types.OwnedGifts: """ Returns the gifts received and owned by a managed business account. Requires the can_view_gifts_and_stars business bot right. Returns OwnedGifts on success. - + Telegram documentation: https://core.telegram.org/bots/api#getbusinessaccountgifts :param business_connection_id: Unique identifier of the business connection @@ -6695,7 +6695,7 @@ def convert_gift_to_stars(self, business_connection_id: str, owned_gift_id: str) :rtype: :obj:`bool` """ return apihelper.convert_gift_to_stars(self.token, business_connection_id, owned_gift_id) - + def upgrade_gift( self, business_connection_id: str, owned_gift_id: str, keep_original_details: Optional[bool]=None, @@ -6759,7 +6759,7 @@ def transfer_gift( new_owner_chat_id, star_count=star_count ) - + def post_story( self, business_connection_id: str, content: types.InputStoryContent, active_period: int, caption: Optional[str]=None, @@ -6866,7 +6866,7 @@ def edit_story( def delete_story(self, business_connection_id: str, story_id: int) -> bool: """ Deletes a story previously posted by the bot on behalf of a managed business account. Requires the can_manage_stories business bot right. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletestory :param business_connection_id: Unique identifier of the business connection @@ -6915,7 +6915,7 @@ def gift_premium_subscription( text=text, text_parse_mode=text_parse_mode, text_entities=text_entities ) - + def set_business_account_profile_photo( self, business_connection_id: str, photo: types.InputProfilePhoto, is_public: Optional[bool]=None) -> bool: @@ -6994,8 +6994,8 @@ def replace_sticker_in_set(self, user_id: int, name: str, old_sticker: str, stic :rtype: :obj:`bool` """ return apihelper.replace_sticker_in_set(self.token, user_id, name, old_sticker, sticker) - - + + def set_sticker_emoji_list(self, sticker: str, emoji_list: List[str]) -> bool: """ Use this method to set the emoji list of a custom emoji sticker set. @@ -7017,7 +7017,7 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s """ Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success. - + Telegram documentation: https://core.telegram.org/bots/api#uploadstickerfile :param user_id: User identifier of sticker set owner @@ -7031,7 +7031,7 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s See https://core.telegram.org/stickers for technical requirements. More information on Sending Files » :type sticker: :class:`telebot.types.InputFile` - :param sticker_format: One of "static", "animated", "video". + :param sticker_format: One of "static", "animated", "video". :type sticker_format: :obj:`str` :return: On success, the sent file is returned. @@ -7041,17 +7041,17 @@ def upload_sticker_file(self, user_id: int, png_sticker: Union[Any, str]=None, s logger.warning('The parameter "png_sticker" is deprecated. Use "sticker" instead.') sticker = png_sticker sticker_format = "static" - + return types.File.de_json( apihelper.upload_sticker_file(self.token, user_id, sticker, sticker_format) ) def create_new_sticker_set( - self, user_id: int, name: str, title: str, - emojis: Optional[List[str]]=None, - png_sticker: Union[Any, str]=None, - tgs_sticker: Union[Any, str]=None, + self, user_id: int, name: str, title: str, + emojis: Optional[List[str]]=None, + png_sticker: Union[Any, str]=None, + tgs_sticker: Union[Any, str]=None, webm_sticker: Union[Any, str]=None, contains_masks: Optional[bool]=None, sticker_type: Optional[str]=None, @@ -7060,7 +7060,7 @@ def create_new_sticker_set( stickers: List[types.InputSticker]=None, sticker_format: Optional[str]=None) -> bool: """ - Use this method to create new sticker set owned by a user. + Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success. @@ -7124,11 +7124,11 @@ def create_new_sticker_set( sticker_format = 'video' elif png_sticker: sticker_format = 'static' - + if contains_masks is not None: logger.warning('The parameter "contains_masks" is deprecated, use "sticker_type" instead') if sticker_type is None: - sticker_type = 'mask' if contains_masks else 'regular' + sticker_type = 'mask' if contains_masks else 'regular' if stickers is None: stickers = png_sticker or tgs_sticker or webm_sticker @@ -7145,8 +7145,8 @@ def create_new_sticker_set( def add_sticker_to_set( self, user_id: int, name: str, emojis: Union[List[str], str], - png_sticker: Optional[Union[Any, str]]=None, - tgs_sticker: Optional[Union[Any, str]]=None, + png_sticker: Optional[Union[Any, str]]=None, + tgs_sticker: Optional[Union[Any, str]]=None, webm_sticker: Optional[Union[Any, str]]=None, mask_position: Optional[types.MaskPosition]=None, sticker: Optional[types.InputSticker]=None) -> bool: @@ -7210,7 +7210,7 @@ def add_sticker_to_set( def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: """ Use this method to move a sticker in a set created by the bot to a specific position . Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#setstickerpositioninset :param sticker: File identifier of the sticker @@ -7228,7 +7228,7 @@ def set_sticker_position_in_set(self, sticker: str, position: int) -> bool: def delete_sticker_from_set(self, sticker: str) -> bool: """ Use this method to delete a sticker from a set created by the bot. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#deletestickerfromset :param sticker: File identifier of the sticker @@ -7388,9 +7388,9 @@ def edit_general_forum_topic(self, chat_id: Union[int, str], name: str) -> bool: Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot must be an administrator in the chat for this to work and must have can_manage_topics administrator rights. Returns True on success. - + Telegram documentation: https://core.telegram.org/bots/api#editgeneralforumtopic - + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format @channelusername) :type chat_id: :obj:`int` or :obj:`str` @@ -7473,7 +7473,7 @@ def answer_web_app_query(self, web_app_query_id: str, result: types.InlineQueryR """ Use this method to set the result of an interaction with a Web App and send a corresponding message on behalf of the user to the chat from which - the query originated. + the query originated. On success, a SentWebAppMessage object is returned. Telegram Documentation: https://core.telegram.org/bots/api#answerwebappquery @@ -7541,7 +7541,7 @@ def register_for_reply(self, message: types.Message, callback: Callable, *args, :param args: Optional arguments for the callback function. :param kwargs: Optional keyword arguments for the callback function. - + :return: None """ self.register_for_reply_by_message_id(message.message_id, callback, *args, **kwargs) @@ -7644,8 +7644,8 @@ def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[in Added additional parameters to support topics, business connections, and message threads. - .. seealso:: - + .. seealso:: + For more details, visit the `custom_states.py example `_. :param user_id: User's identifier @@ -7677,7 +7677,7 @@ def set_state(self, user_id: int, state: Union[str, State], chat_id: Optional[in bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def reset_data(self, user_id: int, chat_id: Optional[int]=None, + def reset_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> bool: """ @@ -7720,7 +7720,7 @@ def delete_state(self, user_id: int, chat_id: Optional[int]=None, business_conne :param user_id: User's identifier :type user_id: :obj:`int` - + :param chat_id: Chat's identifier :type chat_id: :obj:`int` @@ -7775,7 +7775,7 @@ def retrieve_data(self, user_id: int, chat_id: Optional[int]=None, business_conn bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def get_state(self, user_id: int, chat_id: Optional[int]=None, + def get_state(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, message_thread_id: Optional[int]=None, bot_id: Optional[int]=None) -> str: """ @@ -7813,9 +7813,9 @@ def get_state(self, user_id: int, chat_id: Optional[int]=None, bot_id=bot_id, business_connection_id=business_connection_id, message_thread_id=message_thread_id) - def add_data(self, user_id: int, chat_id: Optional[int]=None, + def add_data(self, user_id: int, chat_id: Optional[int]=None, business_connection_id: Optional[str]=None, - message_thread_id: Optional[int]=None, + message_thread_id: Optional[int]=None, bot_id: Optional[int]=None, **kwargs) -> None: """ @@ -7862,7 +7862,7 @@ def register_next_step_handler_by_chat_id( :type callback: :obj:`Callable[[telebot.types.Message], None]` :param args: Args to pass in callback func - + :param kwargs: Args to pass in callback func :return: None @@ -8032,7 +8032,7 @@ def register_middleware_handler(self, callback, update_types=None): bot = TeleBot('TOKEN') bot.register_middleware_handler(print_channel_post_text, update_types=['channel_post', 'edited_channel_post']) - + :param callback: Function that will be used as a middleware handler. :type callback: :obj:`function` @@ -8212,7 +8212,7 @@ def register_message_handler(self, callback: Callable, content_types: Optional[L logger.warning("register_message_handler: 'content_types' filter should be List of strings (content types), not string.") content_types = [content_types] - + handler_dict = self._build_handler_dict(callback, chat_types=chat_types, @@ -8284,7 +8284,7 @@ def add_edited_message_handler(self, handler_dict): """ Adds the edit message handler Note that you should use register_edited_message_handler to add edited_message_handler to the bot. - + :meta private: :param handler_dict: @@ -8406,7 +8406,7 @@ def add_channel_post_handler(self, handler_dict): Note that you should use register_channel_post_handler to add channel_post_handler to the bot. :meta private: - + :param handler_dict: :return: """ @@ -8626,7 +8626,7 @@ def register_message_reaction_handler(self, callback: Callable, func: Callable=N :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) :type pass_bot: :obj:`bool` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -8654,7 +8654,7 @@ def decorator(handler): return decorator - + def add_message_reaction_count_handler(self, handler_dict): """ Adds message reaction count handler @@ -8680,7 +8680,7 @@ def register_message_reaction_count_handler(self, callback: Callable, func: Call :param pass_bot: True if you need to pass TeleBot instance to handler(useful for separating handlers into different files) :type pass_bot: :obj:`bool` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -8751,7 +8751,7 @@ def chosen_inline_handler(self, func, **kwargs): :param func: Function executed as a filter :type func: :obj:`function` - + :param kwargs: Optional keyword arguments(custom filters) :return: None @@ -8807,7 +8807,7 @@ def callback_query_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -8861,7 +8861,7 @@ def shipping_query_handler(self, func, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -8938,7 +8938,7 @@ def add_pre_checkout_query_handler(self, handler_dict): """ self.pre_checkout_query_handlers.append(handler_dict) - + def register_pre_checkout_query_handler(self, callback: Callable, func: Callable, pass_bot: Optional[bool]=False, **kwargs): """ Registers pre-checkout request handler. @@ -8973,9 +8973,9 @@ def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) self.add_purchased_paid_media_handler(handler_dict) return handler - + return decorator - + def add_purchased_paid_media_handler(self, handler_dict): """ Adds a purchased paid media handler @@ -8994,7 +8994,7 @@ def register_purchased_paid_media_handler(self, callback: Callable, func: Callab :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -9071,7 +9071,7 @@ def poll_answer_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -9238,7 +9238,7 @@ def chat_join_request_handler(self, func=None, **kwargs): :type func: :obj:`function` :param kwargs: Optional keyword arguments(custom filters) - + :return: None """ def decorator(handler): @@ -9286,7 +9286,7 @@ def register_chat_join_request_handler( def chat_boost_handler(self, func=None, **kwargs): """ - Handles new incoming chat boost state. + Handles new incoming chat boost state. it passes :class:`telebot.types.ChatBoostUpdated` object. :param func: Function executed as a filter @@ -9323,7 +9323,7 @@ def register_chat_boost_handler( :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -9339,7 +9339,7 @@ def register_chat_boost_handler( def removed_chat_boost_handler(self, func=None, **kwargs): """ - Handles new incoming chat boost state. + Handles new incoming chat boost state. it passes :class:`telebot.types.ChatBoostRemoved` object. :param func: Function executed as a filter @@ -9355,7 +9355,7 @@ def decorator(handler): return decorator - + def add_removed_chat_boost_handler(self, handler_dict): """ Adds a removed_chat_boost handler. @@ -9376,7 +9376,7 @@ def register_removed_chat_boost_handler( :param callback: function to be called :type callback: :obj:`function` - + :param func: Function executed as a filter :type func: :obj:`function` @@ -9404,7 +9404,7 @@ def decorator(handler): handler_dict = self._build_handler_dict(handler, func=func, **kwargs) self.add_business_connection_handler(handler_dict) return handler - + return decorator @@ -9572,7 +9572,7 @@ def register_business_message_handler(self, :return: None """ - handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, + handler_dict = self._build_handler_dict(callback, content_types=content_types, commands=commands, regexp=regexp, func=func, pass_bot=pass_bot, **kwargs) self.add_business_message_handler(handler_dict) @@ -9632,7 +9632,7 @@ def add_edited_business_message_handler(self, handler_dict): """ Adds the edit message handler Note that you should use register_edited_business_message_handler to add edited_business_message_handler to the bot. - + :meta private: :param handler_dict: @@ -9709,7 +9709,7 @@ def decorator(handler): self.add_deleted_business_messages_handler(handler_dict) return handler - + return decorator @@ -9829,7 +9829,7 @@ def _get_middlewares(self, update_type): :return: """ middlewares = None - if self.middlewares: + if self.middlewares: middlewares = [i for i in self.middlewares if update_type in i.update_types] return middlewares From 8335648c81ec82ca9bdb546ff1966fc29ceb7da3 Mon Sep 17 00:00:00 2001 From: Badiboy Date: Wed, 3 Sep 2025 17:57:52 +0300 Subject: [PATCH 479/480] Bump version (fix) --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- telebot/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 514d9dad4..d1aa0b25d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ copyright = f'2022-{datetime.now().year}, {author}' # The full version, including alpha/beta/rc tags -release = '4.29.0' +release = '4.29.1' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 5271bfa16..d226c3d64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyTelegramBotAPI" -version = "4.29.0" +version = "4.29.1" description = "Python Telegram bot API." authors = [{name = "eternnoir", email = "eternnoir@gmail.com"}] license = {text = "GPL2"} diff --git a/telebot/version.py b/telebot/version.py index e4d2a2e0c..14e603359 100644 --- a/telebot/version.py +++ b/telebot/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '4.29.0' +__version__ = '4.29.1' From 5e5661dc857ad52b6fde27130a2d843b8148bce4 Mon Sep 17 00:00:00 2001 From: Savvich Date: Tue, 21 Oct 2025 23:43:48 +0300 Subject: [PATCH 480/480] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 29764fb3c..8a6c7fd96 100644 --- a/README.md +++ b/README.md @@ -572,7 +572,7 @@ Refer [Bot Api](https://core.telegram.org/bots/api#messageentity) for extra deta ## Advanced use of the API -### Using local Bot API Sever +### Using local Bot API Server Since version 5.0 of the Bot API, you have the possibility to run your own [Local Bot API Server](https://core.telegram.org/bots/api#using-a-local-bot-api-server). pyTelegramBotAPI also supports this feature. ```python