1
0
mirror of https://github.com/eternnoir/pyTelegramBotAPI.git synced 2023-08-10 21:12:57 +03:00

Custom exception handler for poll mode

Initial beta of custom exception handler for poll mode.

Use ExceptionHandler class and bot.exception_handler to proceed unhandled exceptions in poll mode.
This commit is contained in:
Badiboy 2020-08-21 17:36:08 +03:00
parent 18eb8eb605
commit 73487f96c4
2 changed files with 75 additions and 19 deletions

View File

@ -42,6 +42,15 @@ class Handler:
return getattr(self, item) return getattr(self, item)
class ExceptionHandler:
"""
Class for handling exceptions while Polling
"""
def handle(self, exception):
return False
class TeleBot: class TeleBot:
""" This is TeleBot Class """ This is TeleBot Class
Methods: Methods:
@ -86,7 +95,7 @@ class TeleBot:
def __init__( def __init__(
self, token, parse_mode=None, threaded=True, skip_pending=False, num_threads=2, self, token, parse_mode=None, threaded=True, skip_pending=False, num_threads=2,
next_step_backend=None, reply_backend=None next_step_backend=None, reply_backend=None, exception_handler=None
): ):
""" """
:param token: bot API token :param token: bot API token
@ -111,6 +120,8 @@ class TeleBot:
if not self.reply_backend: if not self.reply_backend:
self.reply_backend = MemoryHandlerBackend() self.reply_backend = MemoryHandlerBackend()
self.exception_handler = exception_handler
self.message_handlers = [] self.message_handlers = []
self.edited_message_handlers = [] self.edited_message_handlers = []
self.channel_post_handlers = [] self.channel_post_handlers = []
@ -452,6 +463,12 @@ class TeleBot:
error_interval = 0.25 error_interval = 0.25
except apihelper.ApiException as e: except apihelper.ApiException as e:
if self.exception_handler is not None:
handled = self.exception_handler.handle(e)
else:
handled = False
if not handled:
logger.error(e) logger.error(e)
if not none_stop: if not none_stop:
self.__stop_polling.set() self.__stop_polling.set()
@ -462,10 +479,25 @@ class TeleBot:
logger.info("Waiting for {0} seconds until retry".format(error_interval)) logger.info("Waiting for {0} seconds until retry".format(error_interval))
time.sleep(error_interval) time.sleep(error_interval)
error_interval *= 2 error_interval *= 2
else:
polling_thread.clear_exceptions()
self.worker_pool.clear_exceptions()
time.sleep(error_interval)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("KeyboardInterrupt received.") logger.info("KeyboardInterrupt received.")
self.__stop_polling.set() self.__stop_polling.set()
break break
except Exception as e:
if self.exception_handler is not None:
handled = self.exception_handler.handle(e)
else:
handled = False
if not handled:
raise e
else:
polling_thread.clear_exceptions()
self.worker_pool.clear_exceptions()
time.sleep(error_interval)
polling_thread.stop() polling_thread.stop()
logger.info('Stopped polling.') logger.info('Stopped polling.')
@ -480,6 +512,12 @@ class TeleBot:
self.__retrieve_updates(timeout) self.__retrieve_updates(timeout)
error_interval = 0.25 error_interval = 0.25
except apihelper.ApiException as e: except apihelper.ApiException as e:
if self.exception_handler is not None:
handled = self.exception_handler.handle(e)
else:
handled = False
if not handled:
logger.error(e) logger.error(e)
if not none_stop: if not none_stop:
self.__stop_polling.set() self.__stop_polling.set()
@ -488,10 +526,21 @@ class TeleBot:
logger.info("Waiting for {0} seconds until retry".format(error_interval)) logger.info("Waiting for {0} seconds until retry".format(error_interval))
time.sleep(error_interval) time.sleep(error_interval)
error_interval *= 2 error_interval *= 2
else:
time.sleep(error_interval)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("KeyboardInterrupt received.") logger.info("KeyboardInterrupt received.")
self.__stop_polling.set() self.__stop_polling.set()
break break
except Exception as e:
if self.exception_handler is not None:
handled = self.exception_handler.handle(e)
else:
handled = False
if not handled:
raise e
else:
time.sleep(error_interval)
logger.info('Stopped polling.') logger.info('Stopped polling.')
@ -1055,7 +1104,6 @@ class TeleBot:
""" """
return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title) return apihelper.set_chat_administrator_custom_title(self.token, chat_id, user_id, custom_title)
def set_chat_permissions(self, chat_id, permissions): def set_chat_permissions(self, chat_id, permissions):
""" """
Use this method to set default chat permissions for all members. Use this method to set default chat permissions for all members.
@ -1837,6 +1885,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_inline_handler(handler_dict) self.add_inline_handler(handler_dict)
@ -1859,6 +1908,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_chosen_inline_handler(handler_dict) self.add_chosen_inline_handler(handler_dict)
@ -1881,6 +1931,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_callback_query_handler(handler_dict) self.add_callback_query_handler(handler_dict)
@ -1903,6 +1954,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_shipping_query_handler(handler_dict) self.add_shipping_query_handler(handler_dict)
@ -1925,6 +1977,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_pre_checkout_query_handler(handler_dict) self.add_pre_checkout_query_handler(handler_dict)
@ -1947,6 +2000,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_poll_handler(handler_dict) self.add_poll_handler(handler_dict)
@ -1969,6 +2023,7 @@ class TeleBot:
:param kwargs: :param kwargs:
:return: :return:
""" """
def decorator(handler): def decorator(handler):
handler_dict = self._build_handler_dict(handler, func=func, **kwargs) handler_dict = self._build_handler_dict(handler, func=func, **kwargs)
self.add_poll_answer_handler(handler_dict) self.add_poll_answer_handler(handler_dict)

View File

@ -975,6 +975,7 @@ def send_invoice(
:param reply_to_message_id: If the message is a reply, ID of the original message :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 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 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:
:return: :return:
""" """
method_url = r'sendInvoice' method_url = r'sendInvoice'
@ -1288,7 +1289,7 @@ class ApiTelegramException(ApiException):
""" """
def __init__(self, function_name, result, result_json): def __init__(self, function_name, result, result_json):
super(ApiTelegramException, self).__init__( super(ApiTelegramException, self).__init__(
"Error code: {0} Description: {1}" \ "Error code: {0}. Description: {1}" \
.format(result_json['error_code'], result_json['description']), .format(result_json['error_code'], result_json['description']),
function_name, function_name,
result) result)