diff --git a/core.py b/core.py index 4df978a..fcb2c4b 100644 --- a/core.py +++ b/core.py @@ -36,39 +36,8 @@ def main(): # Main loop of the program while True: # Get a new batch of 100 updates and mark the last 100 parsed as read - try: - updates = bot.get_updates(offset=next_update, - timeout=int(configloader.config["Telegram"]["long_polling_timeout"])) - # If the method times out... - except telegram.error.TimedOut: - # Increase the TimedOut counter - timed_out_counter += 1 - # Notify on stdout - print(f"WARNING: get_updates timed out ({timed_out_counter} time{'s' if timed_out_counter != 1 else ''})") - # Try again - continue - # If the method raises a NetworkError (connection problems)... - except telegram.error.NetworkError: - # Increase the TimedOut counter - timed_out_counter += 1 - # Notify on stdout - print(f"ERROR: get_updates raised a NetworkError ({timed_out_counter} time{'s' if timed_out_counter != 1 else ''})") - # Wait some time before retrying - time.sleep(3) - continue - # If Telegram returns an error... - except telegram.error.TelegramError as e: - # Increase the TimedOut counter - timed_out_counter += 1 - # Notify on stdout - print(f"ERROR: telegram returned an error while trying to get_updates ({e.message}) ({timed_out_counter} time{'s' if timed_out_counter != 1 else ''})") - # Wait some time before retrying - time.sleep(3) - continue - # If all goes well... - else: - # Reset the TimedOut counter - timed_out_counter = 0 + updates = bot.get_updates(offset=next_update, + timeout=int(configloader.config["Telegram"]["long_polling_timeout"])) # Parse all the updates for update in updates: # If the update is a message... diff --git a/utils.py b/utils.py index 21574dc..f287ae0 100644 --- a/utils.py +++ b/utils.py @@ -5,6 +5,7 @@ from configloader import config from strings import currency_format_string, currency_symbol import typing + class Price: def __init__(self, value:typing.Union[int, float, str, "Price"]=0): if isinstance(value, int): @@ -92,18 +93,23 @@ def catch_telegram_errors(func): def result_func(*args, **kwargs): while True: try: - func(*args, **kwargs) + return func(*args, **kwargs) + # Bot was blocked by the user except telegram.error.Unauthorized: print(f"Unauthorized to call {func.__name__}(), skipping.") break + # Telegram API didn't answer in time except telegram.error.TimedOut: print(f"Timed out while calling {func.__name__}(), retrying in 1 sec...") time.sleep(1) + # Telegram is not reachable except telegram.error.NetworkError: print(f"Network error while calling {func.__name__}(), retrying in 5 secs...") time.sleep(5) - else: - break + # Unknown error + except telegram.error.TelegramError: + print(f"Telegram error while calling {func.__name__}(), retrying in 5 secs...") + time.sleep(5) return result_func @@ -113,46 +119,46 @@ class DuckBot: @catch_telegram_errors def send_message(self, *args, **kwargs): - self.bot.send_message(*args, **kwargs) + return self.bot.send_message(*args, **kwargs) @catch_telegram_errors def edit_message_text(self, *args, **kwargs): - self.bot.edit_message_text(*args, **kwargs) + return self.bot.edit_message_text(*args, **kwargs) @catch_telegram_errors def edit_message_caption(self, *args, **kwargs): - self.bot.edit_message_caption(*args, **kwargs) + return self.bot.edit_message_caption(*args, **kwargs) @catch_telegram_errors def edit_message_reply_markup(self, *args, **kwargs): - self.bot.edit_message_reply_markup(*args, **kwargs) + return self.bot.edit_message_reply_markup(*args, **kwargs) @catch_telegram_errors def get_updates(self, *args, **kwargs): - self.bot.get_updates(*args, **kwargs) + return self.bot.get_updates(*args, **kwargs) @catch_telegram_errors def get_me(self, *args, **kwargs): - self.bot.get_me(*args, **kwargs) + return self.bot.get_me(*args, **kwargs) @catch_telegram_errors def answer_callback_query(self, *args, **kwargs): - self.bot.answer_callback_query(*args, **kwargs) + return self.bot.answer_callback_query(*args, **kwargs) @catch_telegram_errors def answer_pre_checkout_query(self, *args, **kwargs): - self.bot.answer_pre_checkout_query(*args, **kwargs) + return self.bot.answer_pre_checkout_query(*args, **kwargs) @catch_telegram_errors def send_invoice(self, *args, **kwargs): - self.bot.send_invoice(*args, **kwargs) + return self.bot.send_invoice(*args, **kwargs) @catch_telegram_errors def get_file(self, *args, **kwargs): - self.bot.get_file(*args, **kwargs) + return self.bot.get_file(*args, **kwargs) @catch_telegram_errors def send_chat_action(self, *args, **kwargs): - self.bot.send_chat_action(*args, **kwargs) + return self.bot.send_chat_action(*args, **kwargs) - # TODO: add more methods \ No newline at end of file + # TODO: add more methods diff --git a/worker.py b/worker.py index aa1f1fd..7ccfba3 100644 --- a/worker.py +++ b/worker.py @@ -12,6 +12,7 @@ import re import utils from html import escape + class StopSignal: """A data class that should be sent to the worker when the conversation has to be stopped abnormally.""" @@ -45,7 +46,6 @@ class ChatWorker(threading.Thread): def run(self): """The conversation code.""" - # TODO: catch all the possible exceptions # Welcome the user to the bot self.bot.send_message(self.chat.id, strings.conversation_after_start) # Get the user db data from the users and admin tables @@ -78,6 +78,7 @@ class ChatWorker(threading.Thread): # Wait for the thread to stop self.join() + # noinspection PyUnboundLocalVariable def __receive_next_update(self) -> telegram.Update: """Get the next update from the queue. If no update is found, block the process until one is received. @@ -95,7 +96,9 @@ class ChatWorker(threading.Thread): # Return the received update return data - def __wait_for_specific_message(self, items:typing.List[str], cancellable:bool=False) -> typing.Union[str, CancelSignal]: + def __wait_for_specific_message(self, + items: typing.List[str], + cancellable: bool=False) -> typing.Union[str, CancelSignal]: """Continue getting updates until until one of the strings contained in the list is received as a message.""" while True: # Get the next update @@ -116,7 +119,7 @@ class ChatWorker(threading.Thread): # Return the message text return update.message.text - def __wait_for_regex(self, regex:str, cancellable:bool=False) -> typing.Union[str, CancelSignal]: + def __wait_for_regex(self, regex: str, cancellable: bool=False) -> typing.Union[str, CancelSignal]: """Continue getting updates until the regex finds a match in a message, then return the first capture group.""" while True: # Get the next update @@ -139,7 +142,8 @@ class ChatWorker(threading.Thread): # Return the first capture group return match.group(1) - def __wait_for_precheckoutquery(self, cancellable:bool=False) -> typing.Union[telegram.PreCheckoutQuery, CancelSignal]: + def __wait_for_precheckoutquery(self, + cancellable: bool=False) -> typing.Union[telegram.PreCheckoutQuery, CancelSignal]: """Continue getting updates until a precheckoutquery is received. The payload is checked by the core before forwarding the message.""" while True: