1
Fork 0
mirror of https://github.com/Steffo99/greed.git synced 2024-11-24 14:54:18 +00:00

Handle correctly telegram exceptions

This commit is contained in:
Steffo 2018-04-05 10:34:14 +02:00
parent 2ba2be62ff
commit ffc5bbb5f6
3 changed files with 31 additions and 52 deletions

35
core.py
View file

@ -36,39 +36,8 @@ def main():
# Main loop of the program # Main loop of the program
while True: while True:
# Get a new batch of 100 updates and mark the last 100 parsed as read # Get a new batch of 100 updates and mark the last 100 parsed as read
try: updates = bot.get_updates(offset=next_update,
updates = bot.get_updates(offset=next_update, timeout=int(configloader.config["Telegram"]["long_polling_timeout"]))
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
# Parse all the updates # Parse all the updates
for update in updates: for update in updates:
# If the update is a message... # If the update is a message...

View file

@ -5,6 +5,7 @@ from configloader import config
from strings import currency_format_string, currency_symbol from strings import currency_format_string, currency_symbol
import typing import typing
class Price: class Price:
def __init__(self, value:typing.Union[int, float, str, "Price"]=0): def __init__(self, value:typing.Union[int, float, str, "Price"]=0):
if isinstance(value, int): if isinstance(value, int):
@ -92,18 +93,23 @@ def catch_telegram_errors(func):
def result_func(*args, **kwargs): def result_func(*args, **kwargs):
while True: while True:
try: try:
func(*args, **kwargs) return func(*args, **kwargs)
# Bot was blocked by the user
except telegram.error.Unauthorized: except telegram.error.Unauthorized:
print(f"Unauthorized to call {func.__name__}(), skipping.") print(f"Unauthorized to call {func.__name__}(), skipping.")
break break
# Telegram API didn't answer in time
except telegram.error.TimedOut: except telegram.error.TimedOut:
print(f"Timed out while calling {func.__name__}(), retrying in 1 sec...") print(f"Timed out while calling {func.__name__}(), retrying in 1 sec...")
time.sleep(1) time.sleep(1)
# Telegram is not reachable
except telegram.error.NetworkError: except telegram.error.NetworkError:
print(f"Network error while calling {func.__name__}(), retrying in 5 secs...") print(f"Network error while calling {func.__name__}(), retrying in 5 secs...")
time.sleep(5) time.sleep(5)
else: # Unknown error
break except telegram.error.TelegramError:
print(f"Telegram error while calling {func.__name__}(), retrying in 5 secs...")
time.sleep(5)
return result_func return result_func
@ -113,46 +119,46 @@ class DuckBot:
@catch_telegram_errors @catch_telegram_errors
def send_message(self, *args, **kwargs): def send_message(self, *args, **kwargs):
self.bot.send_message(*args, **kwargs) return self.bot.send_message(*args, **kwargs)
@catch_telegram_errors @catch_telegram_errors
def edit_message_text(self, *args, **kwargs): 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 @catch_telegram_errors
def edit_message_caption(self, *args, **kwargs): 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 @catch_telegram_errors
def edit_message_reply_markup(self, *args, **kwargs): 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 @catch_telegram_errors
def get_updates(self, *args, **kwargs): def get_updates(self, *args, **kwargs):
self.bot.get_updates(*args, **kwargs) return self.bot.get_updates(*args, **kwargs)
@catch_telegram_errors @catch_telegram_errors
def get_me(self, *args, **kwargs): def get_me(self, *args, **kwargs):
self.bot.get_me(*args, **kwargs) return self.bot.get_me(*args, **kwargs)
@catch_telegram_errors @catch_telegram_errors
def answer_callback_query(self, *args, **kwargs): 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 @catch_telegram_errors
def answer_pre_checkout_query(self, *args, **kwargs): 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 @catch_telegram_errors
def send_invoice(self, *args, **kwargs): def send_invoice(self, *args, **kwargs):
self.bot.send_invoice(*args, **kwargs) return self.bot.send_invoice(*args, **kwargs)
@catch_telegram_errors @catch_telegram_errors
def get_file(self, *args, **kwargs): def get_file(self, *args, **kwargs):
self.bot.get_file(*args, **kwargs) return self.bot.get_file(*args, **kwargs)
@catch_telegram_errors @catch_telegram_errors
def send_chat_action(self, *args, **kwargs): 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 # TODO: add more methods

View file

@ -12,6 +12,7 @@ import re
import utils import utils
from html import escape from html import escape
class StopSignal: class StopSignal:
"""A data class that should be sent to the worker when the conversation has to be stopped abnormally.""" """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): def run(self):
"""The conversation code.""" """The conversation code."""
# TODO: catch all the possible exceptions
# Welcome the user to the bot # Welcome the user to the bot
self.bot.send_message(self.chat.id, strings.conversation_after_start) self.bot.send_message(self.chat.id, strings.conversation_after_start)
# Get the user db data from the users and admin tables # 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 # Wait for the thread to stop
self.join() self.join()
# noinspection PyUnboundLocalVariable
def __receive_next_update(self) -> telegram.Update: def __receive_next_update(self) -> telegram.Update:
"""Get the next update from the queue. """Get the next update from the queue.
If no update is found, block the process until one is received. 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 the received update
return data 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.""" """Continue getting updates until until one of the strings contained in the list is received as a message."""
while True: while True:
# Get the next update # Get the next update
@ -116,7 +119,7 @@ class ChatWorker(threading.Thread):
# Return the message text # Return the message text
return update.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.""" """Continue getting updates until the regex finds a match in a message, then return the first capture group."""
while True: while True:
# Get the next update # Get the next update
@ -139,7 +142,8 @@ class ChatWorker(threading.Thread):
# Return the first capture group # Return the first capture group
return match.group(1) 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. """Continue getting updates until a precheckoutquery is received.
The payload is checked by the core before forwarding the message.""" The payload is checked by the core before forwarding the message."""
while True: while True: