Bot API 5.3 changes

- Personalized Commands for different chats
- Custom Placeholders of input field for ReplyKeyboardMarkup and ForceReply.
This commit is contained in:
MAIKS1900 2021-06-26 14:36:14 +03:00
parent e381671645
commit 3e33b7f1cb
4 changed files with 141 additions and 14 deletions

View File

@ -1703,21 +1703,52 @@ class TeleBot:
"""
return apihelper.delete_chat_photo(self.token, chat_id)
def get_my_commands(self) -> List[types.BotCommand]:
def get_my_commands(self,
scope: Optional[Union[
types.BotCommandScopeDefault, types.BotCommandScopeAllPrivateChats,
types.BotCommandScopeAllGroupChats, types.BotCommandScopeAllChatAdministrators,
types.BotCommandScopeChat,
types.BotCommandScopeChatAdministrators, types.BotCommandScopeChatMember]]=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 for the given scope and user language
:param scope: scope of users for which the commands are relevant
:param language_code: A two-letter ISO 639-1 language code
Returns List of BotCommand on success.
"""
result = apihelper.get_my_commands(self.token)
result = apihelper.get_my_commands(self.token, scope, language_code)
return [types.BotCommand.de_json(cmd) for cmd in result]
def set_my_commands(self, commands: List[types.BotCommand]) -> bool:
def set_my_commands(self, commands: List[types.BotCommand],
scope: Optional[Union[
types.BotCommandScopeDefault, types.BotCommandScopeAllPrivateChats,
types.BotCommandScopeAllGroupChats, types.BotCommandScopeAllChatAdministrators,
types.BotCommandScopeChat,
types.BotCommandScopeChatAdministrators, types.BotCommandScopeChatMember]] = None,
language_code: Optional[str]=None) -> bool:
"""
Use this method to change the list of the bot's commands.
:param commands: List of BotCommand. At most 100 commands can be specified.
:param scope: scope of users for which the commands are relevant
:param language_code: A two-letter ISO 639-1 language code
:return:
"""
return apihelper.set_my_commands(self.token, commands)
return apihelper.set_my_commands(self.token, commands, scope, language_code)
def delete_my_commands(self,
scope: Optional[Union[
types.BotCommandScopeDefault, types.BotCommandScopeAllPrivateChats,
types.BotCommandScopeAllGroupChats, types.BotCommandScopeAllChatAdministrators,
types.BotCommandScopeChat,
types.BotCommandScopeChatAdministrators, types.BotCommandScopeChatMember]]=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.
:param scope: scope of users for which the commands are relevant
:param language_code: A two-letter ISO 639-1 language code
:return:
"""
return apihelper.delete_my_commands(self.token, scope, language_code)
def set_chat_title(self, chat_id: Union[int, str], title: str) -> bool:
"""

View File

@ -169,11 +169,6 @@ def get_me(token):
return _make_request(token, method_url)
def get_my_commands(token):
method_url = r'getMyCommands'
return _make_request(token, method_url)
def log_out(token):
method_url = r'logOut'
return _make_request(token, method_url)
@ -1032,9 +1027,33 @@ def set_chat_title(token, chat_id, title):
return _make_request(token, method_url, params=payload, method='post')
def set_my_commands(token, commands):
def get_my_commands(token, scope, language_code):
method_url = r'getMyCommands'
payload = {}
if scope is not None:
payload['scope'] = scope.to_json()
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload, method='post')
def set_my_commands(token, commands, scope, language_code):
method_url = r'setMyCommands'
payload = {'commands': _convert_list_json_serializable(commands)}
if scope is not None:
payload['scope'] = scope.to_json()
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload, method='post')
def delete_my_commands(token, scope, language_code):
method_url = r'deleteMyCommands'
payload = {}
if scope is not None:
payload['scope'] = scope.to_json()
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload, method='post')

View File

@ -848,13 +848,16 @@ class File(JsonDeserializable):
class ForceReply(JsonSerializable):
def __init__(self, selective=None):
def __init__(self, selective=None, input_field_placeholder=None):
self.selective: bool = selective
self.input_field_placeholder = input_field_placeholder
def to_json(self):
json_dict = {'force_reply': True}
if self.selective:
json_dict['selective'] = True
if self.input_field_placeholder:
json_dict['input_field_placeholder'] = self.input_field_placeholder
return json.dumps(json_dict)
@ -872,7 +875,8 @@ class ReplyKeyboardRemove(JsonSerializable):
class ReplyKeyboardMarkup(JsonSerializable):
max_row_keys = 12
def __init__(self, resize_keyboard=None, one_time_keyboard=None, selective=None, row_width=3):
def __init__(self, resize_keyboard=None, one_time_keyboard=None, selective=None, row_width=3,
input_field_placeholder=None):
if row_width > self.max_row_keys:
# Todo: Will be replaced with Exception in future releases
if not DISABLE_KEYLEN_ERROR:
@ -883,6 +887,7 @@ class ReplyKeyboardMarkup(JsonSerializable):
self.one_time_keyboard: bool = one_time_keyboard
self.selective: bool = selective
self.row_width: int = row_width
self.input_field_placeholder = input_field_placeholder
self.keyboard: List[List[KeyboardButton]] = []
def add(self, *args, row_width=None):
@ -926,7 +931,7 @@ class ReplyKeyboardMarkup(JsonSerializable):
:param args: strings
:return: self, to allow function chaining.
"""
return self.add(*args, row_width=self.max_row_keys)
def to_json(self):
@ -942,6 +947,8 @@ class ReplyKeyboardMarkup(JsonSerializable):
json_dict['resize_keyboard'] = True
if self.selective:
json_dict['selective'] = True
if self.input_field_placeholder:
json_dict['input_field_placeholder'] = self.input_field_placeholder
return json.dumps(json_dict)
@ -1270,6 +1277,58 @@ class BotCommand(JsonSerializable, JsonDeserializable):
return {'command': self.command, 'description': self.description}
# BotCommandScopes
class BotCommandScope(JsonSerializable):
def __init__(self, type='default', chat_id=None, user_id=None):
self.type: str = type
self.chat_id: Optional[Union[int, str]] = chat_id
self.user_id: Optional[Union[int, str]] = user_id
def to_json(self):
json_dict = {'type': self.type}
if self.chat_id:
json_dict['chat_id'] = self.chat_id
if self.user_id:
json_dict['user_id'] = self.user_id
return json.dumps(json_dict)
class BotCommandScopeDefault(BotCommandScope):
def __init__(self):
super(BotCommandScopeDefault, self).__init__(type='default')
class BotCommandScopeAllPrivateChats(BotCommandScope):
def __init__(self):
super(BotCommandScopeAllPrivateChats, self).__init__(type='all_private_chats')
class BotCommandScopeAllGroupChats(BotCommandScope):
def __init__(self):
super(BotCommandScopeAllGroupChats, self).__init__(type='all_group_chats')
class BotCommandScopeAllChatAdministrators(BotCommandScope):
def __init__(self):
super(BotCommandScopeAllChatAdministrators, self).__init__(type='all_chat_administrators')
class BotCommandScopeChat(BotCommandScope):
def __init__(self, chat_id=None):
super(BotCommandScopeChat, self).__init__(type='chat', chat_id=chat_id)
class BotCommandScopeChatAdministrators(BotCommandScope):
def __init__(self, chat_id=None):
super(BotCommandScopeChatAdministrators, self).__init__(type='chat_administrators', chat_id=chat_id)
class BotCommandScopeChatMember(BotCommandScope):
def __init__(self, chat_id=None, user_id=None):
super(BotCommandScopeChatMember, self).__init__(type='chat_administrators', chat_id=chat_id, user_id=user_id)
# InlineQuery
class InlineQuery(JsonDeserializable):

View File

@ -546,6 +546,24 @@ class TestTeleBot:
ret_msg = tb.send_document(CHAT_ID, file_data, caption='_italic_', parse_mode='Markdown')
assert ret_msg.caption_entities[0].type == 'italic'
def test_chat_commands(self):
tb = telebot.TeleBot(TOKEN)
command, description, lang = 'command_1', 'description of command 1', 'en'
scope = telebot.types.BotCommandScopeChat(CHAT_ID)
ret_msg = tb.set_my_commands([telebot.types.BotCommand(command, description)], scope, lang)
assert ret_msg is True
ret_msg = tb.get_my_commands(scope, lang)
assert ret_msg[0].command == command
assert ret_msg[0].description == description
ret_msg = tb.delete_my_commands(scope, lang)
assert ret_msg is True
ret_msg = tb.get_my_commands(scope, lang)
assert ret_msg == []
def test_typed_middleware_handler(self):
from telebot import apihelper