diff --git a/config/template_config.ini b/config/template_config.ini
index 5480e64..cef2329 100644
--- a/config/template_config.ini
+++ b/config/template_config.ini
@@ -3,7 +3,7 @@
# Config file parameters
[Config]
; Config file version. DO NOT EDIT THIS!
-version = 10
+version = 11
; Set this to no when you are done editing the file
is_template = yes
@@ -47,4 +47,9 @@ name_required = yes
# Require the email of the user
email_required = yes
# Require the phone number of the user
-phone_required = yes
\ No newline at end of file
+phone_required = yes
+
+# Exception reporting settings
+[Error Reporting]
+# Optional sentry token: get the token at https://sentry.io/
+sentry_token = https://00000000000000000000000000000000:00000000000000000000000000000000@sentry.io/0000000
\ No newline at end of file
diff --git a/strings.py b/strings.py
index 1b5c8a7..a97a02a 100644
--- a/strings.py
+++ b/strings.py
@@ -41,9 +41,6 @@ conversation_after_start = "Ciao!\n" \
conversation_open_user_menu = "Cosa vorresti fare?\n" \
"Hai {credit} sul portafoglio."
-# Conversation: the same message as above but when the first has already been sent
-conversation_open_user_menu_multiple = "Hai bisogno di qualcos'altro?"
-
# Conversation: like above, but for administrators
conversation_open_admin_menu = "Sei un amministratore di greed!\n" \
"Cosa vorresti fare?"
@@ -196,7 +193,8 @@ edit_current_value = "Il valore attuale è:\n" \
# Payment: cash payment info
payment_cash = "Puoi pagare in contanti alla sede fisica del negozio.\n" \
- "Il gestore provvederà ad aggiungere credito al tuo account appena gli avrai consegnato i soldi."
+ "Paga alla cassa, e fornisci al gestore del negozio questo id:\n" \
+ "{user_cash_id}"
# Payment: invoice amount
payment_cc_amount = "Quanti fondi vuoi aggiungere al tuo portafoglio?"
@@ -290,4 +288,11 @@ error_order_already_cleared = "⚠️ Questo ordine è già stato processato."
error_no_orders = "⚠️ Non hai ancora piazzato ordini, quindi non c'è niente da visualizzare!"
# Error: selected user does not exist
-error_user_does_not_exist = "⚠️ L'utente selezionato non esiste."
\ No newline at end of file
+error_user_does_not_exist = "⚠️ L'utente selezionato non esiste."
+
+# Fatal: conversation raised an exception
+fatal_conversation_exception = "☢️ Il bot ha riscontrato un errore fatale durante l'esecuzione e ha interrotto la" \
+ " conversazione.\n" \
+ "L'errore è stato segnalato allo sviluppatore di greed," \
+ " in modo che possa sistemarlo.\n" \
+ "Per avviare una nuova conversazione, invia il comando /start."
\ No newline at end of file
diff --git a/worker.py b/worker.py
index e50d8cc..dec9c8b 100644
--- a/worker.py
+++ b/worker.py
@@ -10,6 +10,7 @@ import queue as queuem
import database as db
import re
import utils
+import os
from html import escape
@@ -43,6 +44,15 @@ class ChatWorker(threading.Thread):
self.queue = queuem.Queue()
# The current active invoice payload; reject all invoices with a different payload
self.invoice_payload = None
+ # The Sentry client for reporting errors encountered by the user
+ if configloader.config["Error Reporting"]["sentry_token"] != \
+ "https://00000000000000000000000000000000:00000000000000000000000000000000@sentry.io/0000000":
+ import raven
+ self.sentry_client = raven.Client(configloader.config["Error Reporting"]["sentry_token"],
+ release=raven.fetch_git_sha(os.path.dirname(__file__)),
+ environment="Dev" if __debug__ else "Prod")
+ else:
+ self.sentry_client = None
def run(self):
"""The conversation code."""
@@ -59,17 +69,28 @@ class ChatWorker(threading.Thread):
self.session.add(self.user)
# Commit the transaction
self.session.commit()
- # If the user is not an admin, send him to the user menu
- if self.admin is None:
- self.__user_menu()
- # If the user is an admin, send him to the admin menu
- else:
- # Clear the live orders flag
- self.admin.live_mode = False
- # Commit the change
- self.session.commit()
- # Open the admin menu
- self.__admin_menu()
+ # Capture exceptions that occour during the conversation
+ try:
+ # If the user is not an admin, send him to the user menu
+ if self.admin is None:
+ self.__user_menu()
+ # If the user is an admin, send him to the admin menu
+ else:
+ # Clear the live orders flag
+ self.admin.live_mode = False
+ # Commit the change
+ self.session.commit()
+ # Open the admin menu
+ self.__admin_menu()
+ except Exception:
+ # Try to notify the user of the exception
+ try:
+ self.bot.send_message(self.chat.id, strings.fatal_conversation_exception)
+ except Exception:
+ pass
+ # If the Sentry integration is enabled, log the exception
+ if self.sentry_client is not None:
+ self.sentry_client.captureException()
def stop(self, reason: str=""):
"""Gracefully stop the worker process"""
@@ -473,7 +494,9 @@ class ChatWorker(threading.Thread):
# If the user has selected the Cash option...
if selection == strings.menu_cash:
# Go to the pay with cash function
- self.__add_credit_cash()
+ self.bot.send_message(self.chat.id,
+ strings.payment_cash.format(user_cash_id=self.user.identifiable_str()),
+ parse_mode="HTML")
# If the user has selected the Credit Card option...
elif selection == strings.menu_credit_card:
# Go to the pay with credit card function
@@ -483,10 +506,6 @@ class ChatWorker(threading.Thread):
# Send him back to the previous menu
return
- def __add_credit_cash(self):
- """Tell the user how to pay with cash at this shop."""
- self.bot.send_message(self.chat.id, strings.payment_cash)
-
def __add_credit_cc(self):
"""Add money to the wallet through a credit card payment."""
# Create a keyboard to be sent later
@@ -867,7 +886,7 @@ class ChatWorker(threading.Thread):
def __create_transaction(self):
"""Edit manually the credit of an user."""
# Find all the users in the database
- users = self.session.query(db.User).all()
+ users = self.session.query(db.User).order_by(db.User.user_id).all()
# Create a list containing all the keyboard button strings
keyboard_buttons = [[strings.menu_cancel]]
# Add to the list all the users