From 65cf8410155cd3b9cb6d4d1ca8499bea9f492cc4 Mon Sep 17 00:00:00 2001 From: SwissCorePy <51398037+SwissCorePy@users.noreply.github.com> Date: Wed, 23 Jun 2021 16:09:40 +0200 Subject: [PATCH 1/6] Update util.py added `allowed_updates` list (used by `_init_._retrieve_all_updates` because `chat_member` is not requested by default) --- telebot/util.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telebot/util.py b/telebot/util.py index cb12577..8af740c 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -38,6 +38,10 @@ content_type_service = [ 'voice_chat_participants_invited', 'message_auto_delete_timer_changed' ] +allowed_updates = ["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" +] class WorkerThread(threading.Thread): count = 0 From 4554cb969f4e7c49ce87006485880f4caa7091b3 Mon Sep 17 00:00:00 2001 From: SwissCorePy <51398037+SwissCorePy@users.noreply.github.com> Date: Wed, 23 Jun 2021 16:10:48 +0200 Subject: [PATCH 2/6] Update __init__.py added handlers for `my_chat_member` and `chat_member` --- telebot/__init__.py | 73 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 8bb417e..d959582 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -155,6 +155,8 @@ class TeleBot: self.pre_checkout_query_handlers = [] self.poll_handlers = [] self.poll_answer_handlers = [] + self.my_chat_member_handlers = [] + self.chat_member_handlers = [] if apihelper.ENABLE_MIDDLEWARE: self.typed_middleware_handlers = { @@ -168,6 +170,9 @@ class TeleBot: 'shipping_query': [], 'pre_checkout_query': [], 'poll': [], + 'poll_answer': [], + 'my_chat_member': [], + 'chat_member': [] } self.default_middleware_handlers = [] @@ -354,7 +359,8 @@ class TeleBot: if self.skip_pending: logger.debug('Skipped {0} pending messages'.format(self.__skip_updates())) 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=util.allowed_updates, timeout=timeout, long_polling_timeout=long_polling_timeout) self.process_new_updates(updates) @@ -374,6 +380,8 @@ class TeleBot: new_pre_checkout_queries = None new_polls = None new_poll_answers = None + new_my_chat_members = None + new_chat_members = None for update in updates: if apihelper.ENABLE_MIDDLEWARE: @@ -422,6 +430,12 @@ class TeleBot: if update.poll_answer: if new_poll_answers is None: new_poll_answers = [] new_poll_answers.append(update.poll_answer) + if update.my_chat_member: + if new_my_chat_members is None: new_my_chat_members = [] + new_my_chat_members.append(update.my_chat_member) + if update.chat_member: + if new_chat_members is None: new_chat_members = [] + new_chat_members.append(update.chat_member) if new_messages: self.process_new_messages(new_messages) @@ -445,6 +459,10 @@ class TeleBot: self.process_new_poll(new_polls) if new_poll_answers: self.process_new_poll_answer(new_poll_answers) + if new_my_chat_members: + self.process_new_my_chat_member(new_my_chat_members) + if new_chat_members: + self.process_new_chat_member(new_chat_members) def process_new_messages(self, new_messages): self._notify_next_handlers(new_messages) @@ -481,6 +499,12 @@ class TeleBot: def process_new_poll_answer(self, poll_answers): self._notify_command_handlers(self.poll_answer_handlers, poll_answers) + + def process_new_my_chat_member(self, my_chat_members): + self._notify_command_handlers(self.my_chat_member_handlers, my_chat_members) + + def process_new_chat_member(self, chat_members): + self._notify_command_handlers(self.chat_member_handlers, chat_members) def process_middlewares(self, update): for update_type, middlewares in self.typed_middleware_handlers.items(): @@ -2665,6 +2689,53 @@ class TeleBot: :return: """ self.poll_answer_handlers.append(handler_dict) + + def my_chat_member_handler(self, func=None, **kwargs): + """ + my_chat_member handler + :param func: + :param kwargs: + :return: + """ + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_my_chat_member_handler(handler_dict) + return handler + + return decorator + + def add_my_chat_member_handler(self, handler_dict): + """ + Adds a my_chat_member handler + :param handler_dict: + :return: + """ + self.my_chat_member_handlers.append(handler_dict) + + def chat_member_handler(self, func=None, **kwargs): + """ + chat_member handler + :param func: + :param kwargs: + :return: + """ + + def decorator(handler): + handler_dict = self._build_handler_dict(handler, func=func, **kwargs) + self.add_chat_member_handler(handler_dict) + return handler + + return decorator + + def add_chat_member_handler(self, handler_dict): + """ + Adds a chat_member handler + :param handler_dict: + :return: + """ + self.chat_member_handlers.append(handler_dict) + def _test_message_handler(self, message_handler, message): """ From 506464e6370183e4047d09bcd87c18c573832168 Mon Sep 17 00:00:00 2001 From: SwissCorePy <51398037+SwissCorePy@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:29:36 +0200 Subject: [PATCH 3/6] Update __init__.py Added the parameter `allowed_updates` to polling and infinity_polling functions --- telebot/__init__.py | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index d959582..967f986 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -350,7 +350,7 @@ class TeleBot: updates = self.get_updates(offset=self.last_update_id + 1, long_polling_timeout=1) return total - def __retrieve_updates(self, timeout=20, long_polling_timeout=20): + def __retrieve_updates(self, timeout=20, long_polling_timeout=20, allowed_updates=None): """ Retrieves any updates from the Telegram API. Registered listeners and applicable message handlers will be notified when a new message arrives. @@ -360,7 +360,7 @@ class TeleBot: logger.debug('Skipped {0} pending messages'.format(self.__skip_updates())) self.skip_pending = False updates = self.get_updates(offset=(self.last_update_id + 1), - allowed_updates=util.allowed_updates, + allowed_updates=allowed_updates, timeout=timeout, long_polling_timeout=long_polling_timeout) self.process_new_updates(updates) @@ -530,7 +530,8 @@ class TeleBot: for listener in self.update_listener: self._exec_task(listener, new_messages) - def infinity_polling(self, timeout=20, long_polling_timeout=20, logger_level=logging.ERROR, *args, **kwargs): + def infinity_polling(self, timeout=20, long_polling_timeout=20, logger_level=logging.ERROR, + allowed_updates=None, *args, **kwargs): """ Wrap polling with infinite loop and exception handling to avoid bot stops polling. @@ -538,11 +539,19 @@ class TeleBot: :param long_polling_timeout: Timeout in seconds for long polling (see API docs) :param logger_level: Custom logging level for infinity_polling logging. Use logger levels from logging as a value. None/NOTSET = no error logging + :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.allowed_updates 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, + so unwanted updates may be received for a short period of time. """ while not self.__stop_polling.is_set(): try: self.polling(none_stop=True, timeout=timeout, long_polling_timeout=long_polling_timeout, - *args, **kwargs) + allowed_updates=allowed_updates *args, **kwargs) except Exception as e: if logger_level and logger_level >= logging.ERROR: logger.error("Infinity polling exception: %s", str(e)) @@ -555,7 +564,8 @@ class TeleBot: if logger_level and logger_level >= logging.INFO: logger.error("Break infinity polling") - def polling(self, none_stop=False, interval=0, timeout=20, long_polling_timeout=20): + def polling(self, none_stop: bool=False, interval: int=0, timeout: int=20, + long_polling_timeout: int=20, allowed_updates: Optional[List[str]]=None): """ This function creates a new Thread that calls an internal __retrieve_updates function. This allows the bot to retrieve Updates automagically and notify listeners and message handlers accordingly. @@ -567,14 +577,22 @@ class TeleBot: :param none_stop: Do not stop polling when an ApiException occurs. :param timeout: Request connection timeout :param long_polling_timeout: Timeout in seconds for long polling (see API docs) + :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.allowed_updates 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, + so unwanted updates may be received for a short period of time. :return: """ if self.threaded: - self.__threaded_polling(none_stop, interval, timeout, long_polling_timeout) + self.__threaded_polling(none_stop, interval, timeout, long_polling_timeout, allowed_updates) else: - self.__non_threaded_polling(none_stop, interval, timeout, long_polling_timeout) + self.__non_threaded_polling(none_stop, interval, timeout, long_polling_timeout, allowed_updates) - def __threaded_polling(self, non_stop=False, interval=0, timeout = None, long_polling_timeout = None): + def __threaded_polling(self, non_stop=False, interval=0, timeout = None, long_polling_timeout = None, allowed_updates=None): logger.info('Started polling.') self.__stop_polling.clear() error_interval = 0.25 @@ -589,7 +607,7 @@ class TeleBot: while not self.__stop_polling.wait(interval): or_event.clear() try: - polling_thread.put(self.__retrieve_updates, timeout, long_polling_timeout) + polling_thread.put(self.__retrieve_updates, timeout, long_polling_timeout, allowed_updates=allowed_updates) or_event.wait() # wait for polling thread finish, polling thread error or thread pool error polling_thread.raise_exceptions() self.worker_pool.raise_exceptions() @@ -640,14 +658,14 @@ class TeleBot: self.worker_pool.clear_exceptions() #* logger.info('Stopped polling.') - def __non_threaded_polling(self, non_stop=False, interval=0, timeout=None, long_polling_timeout=None): + def __non_threaded_polling(self, non_stop=False, interval=0, timeout=None, long_polling_timeout=None, allowed_updates=None): logger.info('Started polling.') self.__stop_polling.clear() error_interval = 0.25 while not self.__stop_polling.wait(interval): try: - self.__retrieve_updates(timeout, long_polling_timeout) + 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: From 0bfefdf15deb305bb46ac76d4ad4c05b64ace3ea Mon Sep 17 00:00:00 2001 From: SwissCorePy <51398037+SwissCorePy@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:57:44 +0200 Subject: [PATCH 4/6] changed allowed_updates in util to update_types i think its more clear name --- telebot/__init__.py | 4 ++-- telebot/util.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 967f986..86f65c6 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -541,7 +541,7 @@ class TeleBot: Use logger levels from logging as a value. None/NOTSET = no error logging :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.allowed_updates for a complete list of available update 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. @@ -579,7 +579,7 @@ class TeleBot: :param long_polling_timeout: Timeout in seconds for long polling (see API docs) :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.allowed_updates for a complete list of available update 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. diff --git a/telebot/util.py b/telebot/util.py index 8af740c..3dd71db 100644 --- a/telebot/util.py +++ b/telebot/util.py @@ -38,9 +38,10 @@ content_type_service = [ 'voice_chat_participants_invited', 'message_auto_delete_timer_changed' ] -allowed_updates = ["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" +update_types = [ + "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" ] class WorkerThread(threading.Thread): From 3d5415433e1749a99925e781fd4f1bd6c4218f7d Mon Sep 17 00:00:00 2001 From: SwissCorePy <51398037+SwissCorePy@users.noreply.github.com> Date: Wed, 23 Jun 2021 22:51:17 +0200 Subject: [PATCH 5/6] Update __init__.py Updated TeleBot doc string and added the missing functions to AsyncTeleBot --- telebot/__init__.py | 75 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/telebot/__init__.py b/telebot/__init__.py index 86f65c6..f06ee73 100644 --- a/telebot/__init__.py +++ b/telebot/__init__.py @@ -73,29 +73,55 @@ class TeleBot: close sendMessage forwardMessage + copyMessage deleteMessage sendPhoto sendAudio sendDocument sendSticker sendVideo + sendVenue sendAnimation sendVideoNote sendLocation sendChatAction sendDice + sendContact + sendInvoice + sendMediaGroup getUserProfilePhotos getUpdates getFile sendPoll + stopPoll + sendGame + setGameScore + getGameHighScores + editMessageText + editMessageCaption + editMessageMedia + editMessageReplyMarkup + editMessageLiveLocation + stopMessageLiveLocation kickChatMember unbanChatMember restrictChatMember promoteChatMember + setChatAdministratorCustomTitle + setChatPermissions createChatInviteLink editChatInviteLink revokeChatInviteLink exportChatInviteLink + setChatStickerSet + deleteChatStickerSet + createNewStickerSet + addStickerToSet + deleteStickerFromSet + setStickerPositionInSet + uploadStickerFile + setStickerSetThumb + getStickerSet setChatPhoto deleteChatPhoto setChatTitle @@ -111,6 +137,8 @@ class TeleBot: getMyCommands setMyCommands answerInlineQuery + answerShippingQuery + answerPreCheckoutQuery """ def __init__( @@ -2808,6 +2836,8 @@ class TeleBot: class AsyncTeleBot(TeleBot): def __init__(self, *args, **kwargs): TeleBot.__init__(self, *args, **kwargs) + + # I'm not sure if `get_updates` should be added here too @util.async_dec() def enable_save_next_step_handlers(self, delay=120, filename="./.handler-saves/step.save"): @@ -2837,6 +2867,22 @@ class AsyncTeleBot(TeleBot): def get_me(self): return TeleBot.get_me(self) + @util.async_dec() + def log_out(self): + return TeleBot.log_out(self) + + @util.async_dec() + def close(self): + return TeleBot.close(self) + + @util.async_dec() + def get_my_commands(self): + return TeleBot.get_my_commands(self) + + @util.async_dec() + def set_my_commands(self, *args, **kwargs): + return TeleBot.set_my_commands(self, *args, **kwargs) + @util.async_dec() def get_file(self, *args): return TeleBot.get_file(self, *args) @@ -2885,6 +2931,10 @@ class AsyncTeleBot(TeleBot): def send_dice(self, *args, **kwargs): return TeleBot.send_dice(self, *args, **kwargs) + @util.async_dec() + def send_animation(self, *args, **kwargs): + return TeleBot.send_animation(self, *args, **kwargs) + @util.async_dec() def forward_message(self, *args, **kwargs): return TeleBot.forward_message(self, *args, **kwargs) @@ -2893,7 +2943,6 @@ class AsyncTeleBot(TeleBot): def copy_message(self, *args, **kwargs): return TeleBot.copy_message(self, *args, **kwargs) - @util.async_dec() def delete_message(self, *args): return TeleBot.delete_message(self, *args) @@ -2969,7 +3018,27 @@ class AsyncTeleBot(TeleBot): @util.async_dec() def promote_chat_member(self, *args, **kwargs): return TeleBot.promote_chat_member(self, *args, **kwargs) + + @util.async_dec() + def set_chat_administrator_custom_title(self, *args, **kwargs): + return TeleBot.set_chat_administrator_custom_title(self, *args, **kwargs) + @util.async_dec() + def set_chat_permissions(self, *args, **kwargs): + return TeleBot.set_chat_permissions(self, *args, **kwargs) + + @util.async_dec() + def create_chat_invite_link(self, *args, **kwargs): + return TeleBot.create_chat_invite_link(self, *args, **kwargs) + + @util.async_dec() + def edit_chat_invite_link(self, *args, **kwargs): + return TeleBot.edit_chat_invite_link(self, *args, **kwargs) + + @util.async_dec() + def revoke_chat_invite_link(self, *args, **kwargs): + return TeleBot.revoke_chat_invite_link(self, *args, **kwargs) + @util.async_dec() def export_chat_invite_link(self, *args): return TeleBot.export_chat_invite_link(self, *args) @@ -3073,6 +3142,10 @@ class AsyncTeleBot(TeleBot): @util.async_dec() def delete_sticker_from_set(self, *args, **kwargs): return TeleBot.delete_sticker_from_set(self, *args, **kwargs) + + @util.async_dec() + def set_sticker_set_thumb(self, *args, **kwargs): + return TeleBot.set_sticker_set_thumb(self, *args, **kwargs) @util.async_dec() def send_poll(self, *args, **kwargs): From ce991e9ac3799b9bff72bd99feb76951ded8c446 Mon Sep 17 00:00:00 2001 From: SwissCorePy <51398037+SwissCorePy@users.noreply.github.com> Date: Wed, 23 Jun 2021 22:52:24 +0200 Subject: [PATCH 6/6] Update types.py added the missing attributes `can_manage_chat` and `can_manage_voice_chats` to ChatMember class --- telebot/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telebot/types.py b/telebot/types.py index d3384c0..ad7e4d3 100644 --- a/telebot/types.py +++ b/telebot/types.py @@ -1174,7 +1174,9 @@ class ChatMember(JsonDeserializable): 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, until_date=None, **kwargs): + can_send_other_messages=None, can_add_web_page_previews=None, + can_manage_chat=None, can_manage_voice_chats=None, + until_date=None, **kwargs): self.user: User = user self.status: str = status self.custom_title: str = custom_title @@ -1194,6 +1196,8 @@ class ChatMember(JsonDeserializable): 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_voice_chats: bool = can_manage_voice_chats self.until_date: int = until_date