From f558724c5f117b58bb43656520a48a24c0c3ab37 Mon Sep 17 00:00:00 2001 From: _run Date: Wed, 3 Jul 2024 16:44:30 +0500 Subject: [PATCH 1/3] 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 2/3] 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 08c08942451efc4e86a8026572bd2078c986486b Mon Sep 17 00:00:00 2001 From: _run Date: Thu, 4 Jul 2024 23:41:49 +0500 Subject: [PATCH 3/3] 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: