From 1824637617c22a977a4ca391e42f9913bca25871 Mon Sep 17 00:00:00 2001 From: Anthony Byuraev Date: Sat, 9 May 2020 20:06:33 +0300 Subject: [PATCH 1/5] UPG: Refactoring InlineKeyboardMarkup --- telebot/types.py | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index f2b3dea..bfe6c77 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -855,17 +855,27 @@ class KeyboardButton(Dictionaryable, JsonSerializable): class InlineKeyboardMarkup(Dictionaryable, JsonSerializable): def __init__(self, row_width=3): + """ + This object represents an inline keyboard that appears + right next to the message it belongs to. + + :return: + """ self.row_width = row_width self.keyboard = [] def add(self, *args): """ - 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"]]} + This method adds buttons to the keyboard without exceeding row_width. + + E.g. InlineKeyboardMarkup#add("A", "B", "C") yields the json result: + {keyboard: [["A"], ["B"], ["C"]]} when row_width is set to 1. - When row_width is set to 2, the following is the result of this function: {keyboard: [["A", "B"], ["C"]]} - See https://core.telegram.org/bots/api#replykeyboardmarkup - :param args: KeyboardButton to append to the keyboard + 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 """ i = 1 row = [] @@ -880,26 +890,28 @@ class InlineKeyboardMarkup(Dictionaryable, JsonSerializable): def row(self, *args): """ - 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"]]}' + Adds a list of InlineKeyboardButton to the keyboard. + This metod does not consider row_width. + + InlineKeyboardMarkup.row("A").row("B", "C").to_json() outputs: + '{keyboard: [["A"], ["B", "C"]]}' See https://core.telegram.org/bots/api#inlinekeyboardmarkup - :param args: strings + + :param args: Array of InlineKeyboardButton to append to the keyboard :return: self, to allow function chaining. """ - btn_array = [] - for button in args: - btn_array.append(button.to_dict()) - self.keyboard.append(btn_array) + button_array = [button.to_dict() for button in args] + self.keyboard.append(button_array) return self def to_json(self): """ - Converts this object to its json representation following the Telegram API guidelines described here: + Converts this object to its json representation + following the Telegram API guidelines described here: https://core.telegram.org/bots/api#inlinekeyboardmarkup :return: """ - json_dict = {'inline_keyboard': self.keyboard} - return json.dumps(json_dict) + return json.dumps(self.to_dict()) def to_dict(self): json_dict = {'inline_keyboard': self.keyboard} From 8be9bcc8ed1ae216756adcc655eac74389eb0693 Mon Sep 17 00:00:00 2001 From: Anthony Byuraev Date: Sat, 9 May 2020 20:28:29 +0300 Subject: [PATCH 2/5] UPG: Add custom_title, slow_mode_delay --- telebot/types.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index bfe6c77..62d74c9 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -183,7 +183,8 @@ class GroupChat(JsonDeserializable): class Chat(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) id = obj['id'] type = obj['type'] @@ -196,10 +197,11 @@ class Chat(JsonDeserializable): description = obj.get('description') invite_link = obj.get('invite_link') pinned_message = Message.de_json(obj.get('pinned_message')) + slow_mode_delay = obj.get('slow_mode_delay') sticker_set_name = obj.get('sticker_set_name') can_set_sticker_set = obj.get('can_set_sticker_set') return cls(id, type, title, username, first_name, last_name, all_members_are_administrators, - photo, description, invite_link, pinned_message, sticker_set_name, can_set_sticker_set) + photo, description, invite_link, pinned_message, slow_mode_delay, sticker_set_name, can_set_sticker_set) def __init__(self, id, type, title=None, username=None, first_name=None, last_name=None, all_members_are_administrators=None, photo=None, description=None, invite_link=None, @@ -1020,6 +1022,7 @@ class ChatMember(JsonDeserializable): obj = cls.check_json(json_string) user = User.de_json(obj['user']) status = obj['status'] + custom_title = obj.get('custom_title') until_date = obj.get('until_date') can_be_edited = obj.get('can_be_edited') can_change_info = obj.get('can_change_info') @@ -1034,7 +1037,7 @@ class ChatMember(JsonDeserializable): can_send_media_messages = obj.get('can_send_media_messages') can_send_other_messages = obj.get('can_send_other_messages') can_add_web_page_previews = obj.get('can_add_web_page_previews') - return cls(user, status, until_date, can_be_edited, can_change_info, can_post_messages, can_edit_messages, + return cls(user, status, custom_title, until_date, can_be_edited, can_change_info, can_post_messages, can_edit_messages, can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, can_send_messages, can_send_media_messages, can_send_other_messages, can_add_web_page_previews) From a80927baf9fa9ec60e7df07d84fdf060f915e11a Mon Sep 17 00:00:00 2001 From: Anthony Byuraev Date: Sat, 9 May 2020 23:23:08 +0300 Subject: [PATCH 3/5] UPG: add setChatAdministratorCustomTitle --- telebot/__init__.py | 14 ++++++++++++++ telebot/apihelper.py | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d67d40a..0c4cf8a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -985,6 +985,20 @@ class TeleBot: can_edit_messages, can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members) + def set_chat_administrator_custom_title(self, chat_id, user_id, custom_title): + """ + Use this method to set a custom title for an administrator + in a supergroup promoted by the bot. + Returns True on success. + :param chat_id: Unique identifier for the target chat or username of the target supergroup + (in the format @supergroupusername) + :param user_id: Unique identifier of the target user + :param custom_title: New custom title for the administrator; + 0-16 characters, emoji are not allowed + :return: + """ + return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title) + def export_chat_invite_link(self, chat_id): """ Use this method to export an invite link to a supergroup or a channel. The bot must be an administrator diff --git a/telebot/apihelper.py b/telebot/apihelper.py index 97a7a66..fbf58c0 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -586,7 +586,6 @@ def restrict_chat_member(token, chat_id, user_id, until_date=None, can_send_mess payload['can_add_web_page_previews'] = can_add_web_page_previews if can_invite_users: payload['can_invite_users'] = can_invite_users - return _make_request(token, method_url, params=payload, method='post') @@ -614,6 +613,13 @@ def promote_chat_member(token, chat_id, user_id, can_change_info=None, can_post_ return _make_request(token, method_url, params=payload, method='post') +def set_chat_administrator_custom_title(token, chat_id, user_id, custom_title): + method_url = 'setChatAdministratorCustomTitle' + payload = { + 'chat_id': chat_id, 'user_id': user_id, 'custom_title': custom_title} + return _make_request(token, method_url, params=payload, method='post') + + def export_chat_invite_link(token, chat_id): method_url = 'exportChatInviteLink' payload = {'chat_id': chat_id} From a60253bf608a26e6761e24febadbb97b1dcdc5b3 Mon Sep 17 00:00:00 2001 From: Anthony Byuraev Date: Mon, 11 May 2020 16:38:09 +0300 Subject: [PATCH 4/5] UPG: Add ChatPermissions, set_chat_permissions --- telebot/__init__.py | 21 ++++++++++++++--- telebot/apihelper.py | 8 +++++++ telebot/types.py | 56 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 0c4cf8a..b51035a 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -547,9 +547,11 @@ class TeleBot: def get_chat_administrators(self, chat_id): """ - Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects - that contains information about all chat administrators except other bots. - :param chat_id: + Use this method to get a list of administrators in a chat. + On success, returns an Array of ChatMember objects that contains + information about all chat administrators except other bots. + :param chat_id: Unique identifier for the target chat or username + of the target supergroup or channel (in the format @channelusername) :return: """ result = apihelper.get_chat_administrators(self.token, chat_id) @@ -999,6 +1001,19 @@ class TeleBot: """ return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title) + + def set_chat_permissions(self, chat_id, permissions): + """ + Use this method to set default chat permissions for all members. + The bot must be an administrator in the group or a supergroup for this to work + and must have the can_restrict_members admin rights. + :param chat_id: Unique identifier for the target chat or username of the target supergroup + (in the format @supergroupusername) + :param permissions: New default chat permissions + :return: + """ + return apihelper.set_chat_permissions(self.token, chat_id, permissions) + def export_chat_invite_link(self, chat_id): """ Use this method to export an invite link to a supergroup or a channel. The bot must be an administrator diff --git a/telebot/apihelper.py b/telebot/apihelper.py index fbf58c0..abb6f3f 100644 --- a/telebot/apihelper.py +++ b/telebot/apihelper.py @@ -620,6 +620,14 @@ def set_chat_administrator_custom_title(token, chat_id, user_id, custom_title): return _make_request(token, method_url, params=payload, method='post') +def set_chat_permissions(token, chat_id, permissions): + method_url = 'setChatPermissions' + payload = { + 'chat_id': chat_id, + 'permissions': _convert_list_json_serializable(permissions)} + return _make_request(token, method_url, params=payload, method='post') + + def export_chat_invite_link(token, chat_id): method_url = 'exportChatInviteLink' payload = {'chat_id': chat_id} diff --git a/telebot/types.py b/telebot/types.py index 62d74c9..fe62bc5 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1062,6 +1062,62 @@ class ChatMember(JsonDeserializable): self.can_add_web_page_previews = can_add_web_page_previews +class ChatPermissions(JsonDeserializable, JsonSerializable, Dictionaryable): + def __init__(self, can_send_messages=None, can_send_media_messages=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): + self.can_send_messages = can_send_messages + self.can_send_media_messages = can_send_media_messages + self.can_send_polls = can_send_polls + self.can_send_other_messages = can_send_other_messages + self.can_add_web_page_previews = can_add_web_page_previews + self.can_change_info = can_change_info + self.can_invite_users = can_invite_users + self.can_pin_messages = can_pin_messages + + @classmethod + def de_json(cls, json_string): + if json_string is None: + return json_string + obj = cls.check_json(json_string) + can_send_messages = obj.get('can_send_messages') + can_send_media_messages = obj.get('can_send_media_messages') + can_send_polls = obj.get('can_send_polls') + can_send_other_messages = obj.get('can_send_other_messages') + can_add_web_page_previews = obj.get('can_add_web_page_previews') + can_change_info = obj.get('can_change_info') + can_invite_users = obj.get('can_invite_users') + can_pin_messages = obj.get('can_pin_messages') + return cls( + can_send_messages, can_send_media_messages, can_send_polls, + can_send_other_messages, can_add_web_page_previews, + can_change_info, can_invite_users, can_pin_messages) + + def to_json(self): + return json.dumps(self.to_dict()) + + def to_dict(self): + json_dict = dict() + if self.can_send_messages is not None: + json_dict['can_send_messages'] = self.can_send_messages + if self.can_send_media_messages is not None: + json_dict['can_send_media_messages'] = self.can_send_media_messages + if self.can_send_polls is not None: + json_dict['can_send_polls'] = self.can_send_polls + if self.can_send_other_messages is not None: + json_dict['can_send_other_messages'] = self.can_send_other_messages + if self.can_add_web_page_previews is not None: + json_dict['can_add_web_page_previews'] = self.can_add_web_page_previews + if self.can_change_info is not None: + json_dict['can_change_info'] = self.can_change_info + if self.can_invite_users is not None: + json_dict['can_invite_users'] = self.can_invite_users + if self.can_pin_messages is not None: + json_dict['can_pin_messages'] = self.can_pin_messages + return json_dict + + class BotCommand(JsonSerializable): def __init__(self, command, description): """ From ee00d0458d5c118e121d09ac2bfe81d4c88fcba1 Mon Sep 17 00:00:00 2001 From: Anthony Byuraev Date: Mon, 11 May 2020 22:26:03 +0300 Subject: [PATCH 5/5] Fix some bugs --- telebot/types.py | 65 +++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/telebot/types.py b/telebot/types.py index fe62bc5..37ec7b8 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -183,7 +183,7 @@ class GroupChat(JsonDeserializable): class Chat(JsonDeserializable): @classmethod def de_json(cls, json_string): - if (json_string is None): + if json_string is None: return None obj = cls.check_json(json_string) id = obj['id'] @@ -197,26 +197,34 @@ class Chat(JsonDeserializable): description = obj.get('description') invite_link = obj.get('invite_link') pinned_message = Message.de_json(obj.get('pinned_message')) + permissions = ChatPermissions.de_json(obj.get('permissions')) slow_mode_delay = obj.get('slow_mode_delay') sticker_set_name = obj.get('sticker_set_name') can_set_sticker_set = obj.get('can_set_sticker_set') - return cls(id, type, title, username, first_name, last_name, all_members_are_administrators, - photo, description, invite_link, pinned_message, slow_mode_delay, sticker_set_name, can_set_sticker_set) + return cls( + id, type, title, username, first_name, last_name, + all_members_are_administrators, photo, description, invite_link, + pinned_message, permissions, slow_mode_delay, sticker_set_name, + can_set_sticker_set) - def __init__(self, id, type, title=None, username=None, first_name=None, last_name=None, - all_members_are_administrators=None, photo=None, description=None, invite_link=None, - pinned_message=None, sticker_set_name=None, can_set_sticker_set=None): - self.type = type - self.last_name = last_name - self.first_name = first_name - self.username = username + def __init__(self, id, type, title=None, username=None, first_name=None, + last_name=None, all_members_are_administrators=None, + photo=None, description=None, invite_link=None, + pinned_message=None, permissions=None, slow_mode_delay=None, + sticker_set_name=None, can_set_sticker_set=None): self.id = id + self.type = type self.title = title + self.username = username + self.first_name = first_name + self.last_name = last_name self.all_members_are_administrators = all_members_are_administrators self.photo = photo self.description = description self.invite_link = invite_link self.pinned_message = pinned_message + self.permissions = permissions + self.slow_mode_delay = slow_mode_delay self.sticker_set_name = sticker_set_name self.can_set_sticker_set = can_set_sticker_set @@ -1017,7 +1025,7 @@ class ChatPhoto(JsonDeserializable): class ChatMember(JsonDeserializable): @classmethod def de_json(cls, json_string): - if (json_string is None): + if json_string is None: return None obj = cls.check_json(json_string) user = User.de_json(obj['user']) @@ -1025,39 +1033,50 @@ class ChatMember(JsonDeserializable): custom_title = obj.get('custom_title') until_date = obj.get('until_date') can_be_edited = obj.get('can_be_edited') - can_change_info = obj.get('can_change_info') can_post_messages = obj.get('can_post_messages') can_edit_messages = obj.get('can_edit_messages') can_delete_messages = obj.get('can_delete_messages') - can_invite_users = obj.get('can_invite_users') can_restrict_members = obj.get('can_restrict_members') - can_pin_messages = obj.get('can_pin_messages') can_promote_members = obj.get('can_promote_members') + can_change_info = obj.get('can_change_info') + can_invite_users = obj.get('can_invite_users') + can_pin_messages = obj.get('can_pin_messages') + is_member = obj.get('is_member') can_send_messages = obj.get('can_send_messages') can_send_media_messages = obj.get('can_send_media_messages') + can_send_polls = obj.get('can_send_polls') can_send_other_messages = obj.get('can_send_other_messages') can_add_web_page_previews = obj.get('can_add_web_page_previews') - return cls(user, status, custom_title, until_date, can_be_edited, can_change_info, can_post_messages, can_edit_messages, - can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, - can_send_messages, can_send_media_messages, can_send_other_messages, can_add_web_page_previews) + return cls( + user, status, custom_title, until_date, can_be_edited, can_post_messages, + can_edit_messages, can_delete_messages, can_restrict_members, + can_promote_members, can_change_info, can_invite_users, can_pin_messages, + is_member, can_send_messages, can_send_media_messages, can_send_polls, + can_send_other_messages, can_add_web_page_previews) - def __init__(self, user, status, until_date, can_be_edited, can_change_info, can_post_messages, can_edit_messages, - can_delete_messages, can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, - can_send_messages, can_send_media_messages, can_send_other_messages, can_add_web_page_previews): + def __init__(self, user, status, custom_title=None, until_date=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_media_messages=None, can_send_polls=None, + can_send_other_messages=None, can_add_web_page_previews=None): self.user = user self.status = status + self.custom_title = custom_title self.until_date = until_date self.can_be_edited = can_be_edited - self.can_change_info = can_change_info self.can_post_messages = can_post_messages self.can_edit_messages = can_edit_messages self.can_delete_messages = can_delete_messages - self.can_invite_users = can_invite_users self.can_restrict_members = can_restrict_members - self.can_pin_messages = can_pin_messages self.can_promote_members = can_promote_members + self.can_change_info = can_change_info + self.can_invite_users = can_invite_users + self.can_pin_messages = can_pin_messages + self.is_member = is_member self.can_send_messages = can_send_messages self.can_send_media_messages = can_send_media_messages + self.can_send_polls = can_send_polls self.can_send_other_messages = can_send_other_messages self.can_add_web_page_previews = can_add_web_page_previews