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

Fix #27 by removing the character limit on regexes

This commit is contained in:
Steffo 2020-03-13 02:54:23 +01:00
parent 16e6b16fb0
commit 2b23bd5661
2 changed files with 52 additions and 51 deletions

View file

@ -28,6 +28,7 @@ else:
class Price: class Price:
"""The base class for the prices in greed. """The base class for the prices in greed.
Its int value is in minimum units, while its float and str values are in decimal format.int(""" Its int value is in minimum units, while its float and str values are in decimal format.int("""
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):
# Keep the value as it is # Keep the value as it is
@ -120,6 +121,7 @@ def telegram_html_escape(string: str):
def catch_telegram_errors(func): def catch_telegram_errors(func):
"""Decorator, can be applied to any function to retry in case of Telegram errors.""" """Decorator, can be applied to any function to retry in case of Telegram errors."""
def result_func(*args, **kwargs): def result_func(*args, **kwargs):
while True: while True:
try: try:
@ -137,8 +139,7 @@ def catch_telegram_errors(func):
except telegram.error.NetworkError as error: except telegram.error.NetworkError as error:
print(f"Network error while calling {func.__name__}()," print(f"Network error while calling {func.__name__}(),"
f" retrying in {config['Telegram']['error_pause']} secs...") f" retrying in {config['Telegram']['error_pause']} secs...")
# Display the full NetworkError if in debug mode # Display the full NetworkError
if __debug__:
print(f"Full error: {error.message}") print(f"Full error: {error.message}")
time.sleep(int(config["Telegram"]["error_pause"])) time.sleep(int(config["Telegram"]["error_pause"]))
# Unknown error # Unknown error
@ -154,13 +155,13 @@ def catch_telegram_errors(func):
else: else:
print(f"Telegram error while calling {func.__name__}()," print(f"Telegram error while calling {func.__name__}(),"
f" retrying in {config['Telegram']['error_pause']} secs...") f" retrying in {config['Telegram']['error_pause']} secs...")
# Display the full TelegramError if in debug mode # Display the full TelegramError
if __debug__:
print(f"Full error: {error.message}") print(f"Full error: {error.message}")
# Send the error to the Sentry server # Send the error to the Sentry server
elif sentry_client is not None: if sentry_client is not None:
sentry_client.captureException(exc_info=sys.exc_info()) sentry_client.captureException(exc_info=sys.exc_info())
time.sleep(int(config["Telegram"]["error_pause"])) time.sleep(int(config["Telegram"]["error_pause"]))
return result_func return result_func

View file

@ -1,5 +1,5 @@
import threading import threading
import typing from typing import *
import uuid import uuid
import datetime import datetime
import telegram import telegram
@ -17,6 +17,7 @@ import importlib
language = configloader.config["Config"]["language"] language = configloader.config["Config"]["language"]
strings = importlib.import_module("strings." + language) strings = importlib.import_module("strings." + language)
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."""
@ -41,8 +42,8 @@ class ChatWorker(threading.Thread):
# Open a new database session # Open a new database session
self.session = db.Session() self.session = db.Session()
# Get the user db data from the users and admin tables # Get the user db data from the users and admin tables
self.user: typing.Optional[db.User] = None self.user: Optional[db.User] = None
self.admin: typing.Optional[db.Admin] = None self.admin: Optional[db.Admin] = None
# The sending pipe is stored in the ChatWorker class, allowing the forwarding of messages to the chat process # The sending pipe is stored in the ChatWorker class, allowing the forwarding of messages to the chat process
self.queue = queuem.Queue() self.queue = queuem.Queue()
# The current active invoice payload; reject all invoices with a different payload # The current active invoice payload; reject all invoices with a different payload
@ -144,8 +145,8 @@ class ChatWorker(threading.Thread):
return data return data
def __wait_for_specific_message(self, def __wait_for_specific_message(self,
items: typing.List[str], items: List[str],
cancellable: bool=False) -> typing.Union[str, CancelSignal]: cancellable: bool = False) -> 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
@ -170,7 +171,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) -> 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
@ -194,7 +195,7 @@ class ChatWorker(threading.Thread):
return match.group(1) return match.group(1)
def __wait_for_precheckoutquery(self, def __wait_for_precheckoutquery(self,
cancellable: bool=False) -> typing.Union[telegram.PreCheckoutQuery, CancelSignal]: cancellable: bool = False) -> 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:
@ -224,7 +225,7 @@ class ChatWorker(threading.Thread):
# Return the successfulpayment # Return the successfulpayment
return update.message.successful_payment return update.message.successful_payment
def __wait_for_photo(self, cancellable: bool=False) -> typing.Union[typing.List[telegram.PhotoSize], CancelSignal]: def __wait_for_photo(self, cancellable: bool = False) -> Union[List[telegram.PhotoSize], CancelSignal]:
"""Continue getting updates until a photo is received, then return it.""" """Continue getting updates until a photo is received, then return it."""
while True: while True:
# Get the next update # Get the next update
@ -243,7 +244,7 @@ class ChatWorker(threading.Thread):
return update.message.photo return update.message.photo
def __wait_for_inlinekeyboard_callback(self, cancellable: bool = True) \ def __wait_for_inlinekeyboard_callback(self, cancellable: bool = True) \
-> typing.Union[telegram.CallbackQuery, CancelSignal]: -> Union[telegram.CallbackQuery, CancelSignal]:
"""Continue getting updates until an inline keyboard callback is received, then return it.""" """Continue getting updates until an inline keyboard callback is received, then return it."""
while True: while True:
# Get the next update # Get the next update
@ -260,7 +261,7 @@ class ChatWorker(threading.Thread):
# Return the callbackquery # Return the callbackquery
return update.callback_query return update.callback_query
def __user_select(self) -> typing.Union[db.User, CancelSignal]: def __user_select(self) -> Union[db.User, CancelSignal]:
"""Select an user from the ones in the database.""" """Select an user from the ones in the database."""
# Find all the users in the database # Find all the users in the database
users = self.session.query(db.User).order_by(db.User.user_id).all() users = self.session.query(db.User).order_by(db.User.user_id).all()
@ -335,7 +336,7 @@ class ChatWorker(threading.Thread):
products = self.session.query(db.Product).filter_by(deleted=False).all() products = self.session.query(db.Product).filter_by(deleted=False).all()
# Create a dict to be used as 'cart' # Create a dict to be used as 'cart'
# The key is the message id of the product list # The key is the message id of the product list
cart: typing.Dict[typing.List[db.Product, int]] = {} cart: Dict[List[db.Product, int]] = {}
# Initialize the products list # Initialize the products list
for product in products: for product in products:
# If the product is not for sale, don't display it # If the product is not for sale, don't display it
@ -363,7 +364,7 @@ class ChatWorker(threading.Thread):
inline_keyboard = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_cancel, inline_keyboard = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_cancel,
callback_data="cart_cancel")]]) callback_data="cart_cancel")]])
# Send a message containing the button to cancel or pay # Send a message containing the button to cancel or pay
final = self.bot.send_message(self.chat.id, strings.conversation_cart_actions, reply_markup=inline_keyboard) final_msg = self.bot.send_message(self.chat.id, strings.conversation_cart_actions, reply_markup=inline_keyboard)
# Wait for user input # Wait for user input
while True: while True:
callback = self.__wait_for_inlinekeyboard_callback() callback = self.__wait_for_inlinekeyboard_callback()
@ -411,7 +412,7 @@ class ChatWorker(threading.Thread):
if cart[product_id][1] > 0: if cart[product_id][1] > 0:
product_list += cart[product_id][0].text(style="short", cart_qty=cart[product_id][1]) + "\n" product_list += cart[product_id][0].text(style="short", cart_qty=cart[product_id][1]) + "\n"
total_cost += cart[product_id][0].price * cart[product_id][1] total_cost += cart[product_id][0].price * cart[product_id][1]
self.bot.edit_message_text(chat_id=self.chat.id, message_id=final.message_id, self.bot.edit_message_text(chat_id=self.chat.id, message_id=final_msg.message_id,
text=strings.conversation_confirm_cart.format(product_list=product_list, text=strings.conversation_confirm_cart.format(product_list=product_list,
total_cost=str(total_cost)), total_cost=str(total_cost)),
reply_markup=final_inline_keyboard) reply_markup=final_inline_keyboard)
@ -459,7 +460,7 @@ class ChatWorker(threading.Thread):
if cart[product_id][1] > 0: if cart[product_id][1] > 0:
product_list += cart[product_id][0].text(style="short", cart_qty=cart[product_id][1]) + "\n" product_list += cart[product_id][0].text(style="short", cart_qty=cart[product_id][1]) + "\n"
total_cost += cart[product_id][0].price * cart[product_id][1] total_cost += cart[product_id][0].price * cart[product_id][1]
self.bot.edit_message_text(chat_id=self.chat.id, message_id=final.message_id, self.bot.edit_message_text(chat_id=self.chat.id, message_id=final_msg.message_id,
text=strings.conversation_confirm_cart.format(product_list=product_list, text=strings.conversation_confirm_cart.format(product_list=product_list,
total_cost=str(total_cost)), total_cost=str(total_cost)),
reply_markup=final_inline_keyboard) reply_markup=final_inline_keyboard)
@ -586,8 +587,7 @@ class ChatWorker(threading.Thread):
self.bot.send_message(self.chat.id, strings.payment_cc_amount, self.bot.send_message(self.chat.id, strings.payment_cc_amount,
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True)) reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
# Wait until a valid amount is sent # Wait until a valid amount is sent
# TODO: check and debug the regex selection = self.__wait_for_regex(r"([0-9]+(?:[.,][0-9]+)?|" + strings.menu_cancel + r")")
selection = self.__wait_for_regex(r"([0-9]{1,3}(?:[.,][0-9]+)?|" + strings.menu_cancel + r")")
# If the user cancelled the action # If the user cancelled the action
if selection == strings.menu_cancel: if selection == strings.menu_cancel:
# Exit the loop # Exit the loop
@ -764,7 +764,7 @@ class ChatWorker(threading.Thread):
# Open the edit menu for that specific product # Open the edit menu for that specific product
self.__edit_product_menu(product=product) self.__edit_product_menu(product=product)
def __edit_product_menu(self, product: typing.Optional[db.Product]=None): def __edit_product_menu(self, product: Optional[db.Product] = None):
"""Add a product to the database or edit an existing one.""" """Add a product to the database or edit an existing one."""
# Create an inline keyboard with a single skip button # Create an inline keyboard with a single skip button
cancel = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_skip, cancel = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_skip,
@ -805,7 +805,7 @@ class ChatWorker(threading.Thread):
if product.price is not None else 'Non in vendita')), if product.price is not None else 'Non in vendita')),
reply_markup=cancel) reply_markup=cancel)
# Wait for an answer # Wait for an answer
price = self.__wait_for_regex(r"([0-9]{1,3}(?:[.,][0-9]{1,2})?|[Xx])", price = self.__wait_for_regex(r"([0-9]+(?:[.,][0-9]{1,2})?|[Xx])",
cancellable=True) cancellable=True)
# If the price is skipped # If the price is skipped
if isinstance(price, CancelSignal): if isinstance(price, CancelSignal):