mirror of
https://github.com/Steffo99/greed.git
synced 2024-11-21 13:34:18 +00:00
Add "Create Transaction" menu option and fix image formatting
This commit is contained in:
parent
e8250cd64d
commit
c573c4db62
3 changed files with 114 additions and 30 deletions
38
database.py
38
database.py
|
@ -57,6 +57,10 @@ class User(TableDeclarativeBase):
|
|||
else:
|
||||
return self.first_name
|
||||
|
||||
def identifiable_str(self):
|
||||
"""Describe the user in the best way possible, ensuring a way back to the database record exists."""
|
||||
return f"user_{self.user_id} ({str(self)})"
|
||||
|
||||
def mention(self):
|
||||
"""Mention the user in the best way possible given the available data."""
|
||||
if self.username is not None:
|
||||
|
@ -107,18 +111,11 @@ class Product(TableDeclarativeBase):
|
|||
cart = strings.in_cart_format_string.format(quantity=cart_qty)
|
||||
else:
|
||||
cart = ''
|
||||
return strings.order_format_string.format(name=escape(self.name),
|
||||
description=escape(self.description),
|
||||
stock=stock,
|
||||
price=str(Price(self.price)),
|
||||
cart=cart)
|
||||
elif style == "image":
|
||||
print("WARNING: image text is obsolete and shouldn't be used anymore")
|
||||
return f"{escape(self.name)}\n" \
|
||||
f"{escape(self.description)}\n" \
|
||||
f"{strings.in_stock_format_string.format(quantity=self.stock) if self.stock is not None else ''}\n" \
|
||||
f"{str(Price(self.price))}\n" \
|
||||
f"{strings.in_cart_format_string.format(quantity=cart_qty) if cart_qty is not None else ''}"
|
||||
return strings.product_format_string.format(name=escape(self.name),
|
||||
description=escape(self.description),
|
||||
stock=stock,
|
||||
price=str(Price(self.price)),
|
||||
cart=cart)
|
||||
else:
|
||||
raise ValueError("style is not an accepted value")
|
||||
|
||||
|
@ -136,7 +133,7 @@ class Product(TableDeclarativeBase):
|
|||
r = requests.post(f"https://api.telegram.org/bot{configloader.config['Telegram']['token']}/sendPhoto",
|
||||
files={"photo": self.image},
|
||||
params={"chat_id": chat_id,
|
||||
"caption": self.text(style="image"),
|
||||
"caption": self.text(),
|
||||
"parse_mode": "HTML"})
|
||||
return r.json()
|
||||
|
||||
|
@ -186,12 +183,13 @@ class Transaction(TableDeclarativeBase):
|
|||
__table_args__ = (UniqueConstraint("provider", "provider_charge_id"),)
|
||||
|
||||
def __str__(self):
|
||||
"""Return the correctly formatted transaction value"""
|
||||
# Add a plus symbol if the value is positive
|
||||
string = "+" if self.value > 0 else ""
|
||||
# Add the correctly formatted value
|
||||
string += strings.currency_format_string.format(symbol=strings.currency_symbol, value=self.value)
|
||||
# Return the created string
|
||||
string = f"<b>T{self.transaction_id}</b> | {str(self.user)} | {Price(self.value)}"
|
||||
if self.refunded:
|
||||
string += f" | {strings.emoji_refunded}"
|
||||
if self.provider:
|
||||
string += f" | {self.provider}"
|
||||
if self.notes:
|
||||
string += f" | {self.notes}"
|
||||
return string
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -207,7 +205,7 @@ class Admin(TableDeclarativeBase):
|
|||
# Permissions
|
||||
edit_products = Column(Boolean, default=True)
|
||||
receive_orders = Column(Boolean, default=True)
|
||||
view_transactions = Column(Boolean, default=True)
|
||||
create_transactions = Column(Boolean, default=True)
|
||||
# Live mode enabled
|
||||
live_mode = Column(Boolean, default=False)
|
||||
|
||||
|
|
26
strings.py
26
strings.py
|
@ -57,6 +57,9 @@ conversation_admin_select_product = "✏️ Che prodotto vuoi modificare?"
|
|||
# Conversation: select a product to delete
|
||||
conversation_admin_select_product_to_delete = "❌ Che prodotto vuoi eliminare?"
|
||||
|
||||
# Conversation: select a user to edit
|
||||
conversation_admin_select_user = "✏️ Che utente vuoi modificare?"
|
||||
|
||||
# Conversation: add extra notes to the order
|
||||
conversation_extra_notes = "Che messaggio vuoi lasciare insieme al tuo ordine?"
|
||||
|
||||
|
@ -105,6 +108,9 @@ menu_orders = "📦 Ordini"
|
|||
# Menu: transactions
|
||||
menu_transactions = "💳 Transazioni"
|
||||
|
||||
# Menu: edit credit
|
||||
menu_edit_credit = "💰 Crea transazione"
|
||||
|
||||
# Admin menu: go to user mode
|
||||
menu_user_mode = "👤 Passa alla modalità utente"
|
||||
|
||||
|
@ -142,7 +148,7 @@ menu_add_to_cart = "➕ Aggiungi"
|
|||
menu_remove_from_cart = "➖ Rimuovi"
|
||||
|
||||
# Emoji: unprocessed order
|
||||
emoji_not_processed = "*️⃣ "
|
||||
emoji_not_processed = "*️⃣"
|
||||
|
||||
# Emoji: completed order
|
||||
emoji_completed = "✅"
|
||||
|
@ -171,6 +177,14 @@ ask_order_notes = "Vuoi lasciare un messaggio insieme all'ordine?\n" \
|
|||
ask_refund_reason = "Allega una motivazione a questo rimborso.\n" \
|
||||
"Sarà visibile al cliente."
|
||||
|
||||
# Edit credit: notes?
|
||||
ask_transaction_notes = "Allega una nota a questa transazione.\n" \
|
||||
"Sarà visibile al cliente in seguito all'accredito / addebito e nel registro delle transazioni."
|
||||
|
||||
# Edit credit: amount?
|
||||
ask_credit = "Di quanto vuoi modificare il credito dell'utente?\n" \
|
||||
"(Se vuoi addebitargli soldi, aggiungi un - davanti al numero.)"
|
||||
|
||||
# Thread has started downloading an image and might be unresponsive
|
||||
downloading_image = "Sto scaricando la tua foto!\n" \
|
||||
"Potrei metterci un po'... Abbi pazienza!\n" \
|
||||
|
@ -211,6 +225,10 @@ notification_order_completed = "Un tuo ordine è stato completato!\n" \
|
|||
notification_order_refunded = "Un tuo ordine è stato rimborsato!\n" \
|
||||
"{order}"
|
||||
|
||||
# Notification: a manual transaction was applied
|
||||
notification_transaction_created = "E' stata applicata una nuova transazione al tuo portafoglio:\n" \
|
||||
"{transaction}"
|
||||
|
||||
# Refund reason
|
||||
refund_reason = "Motivazione del rimborso:\n" \
|
||||
"{reason}"
|
||||
|
@ -236,6 +254,9 @@ success_order_completed = "✅ Hai segnato l'ordine #{order_id} come completato.
|
|||
# Success: order was refunded successfully
|
||||
success_order_refunded = "✴️ L'ordine #{order_id} è stato rimborsato con successo."
|
||||
|
||||
# Success: transaction was created successfully
|
||||
success_transaction_created = "✅ La transazione è stata creata con successo!"
|
||||
|
||||
# Error: message received not in a private chat
|
||||
error_nonprivate_chat = "⚠️ Questo bot funziona solo in chat private."
|
||||
|
||||
|
@ -267,3 +288,6 @@ error_order_already_cleared = "⚠️ Questo ordine è già stato processato."
|
|||
|
||||
# Error: no orders have been placed, so none can be shown
|
||||
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."
|
80
worker.py
80
worker.py
|
@ -273,7 +273,7 @@ class ChatWorker(threading.Thread):
|
|||
else:
|
||||
self.bot.edit_message_caption(chat_id=self.chat.id,
|
||||
message_id=message['result']['message_id'],
|
||||
caption=product.text(style="image"),
|
||||
caption=product.text(),
|
||||
parse_mode="HTML",
|
||||
reply_markup=inline_keyboard)
|
||||
# Create the keyboard with the cancel button
|
||||
|
@ -317,8 +317,7 @@ class ChatWorker(threading.Thread):
|
|||
else:
|
||||
self.bot.edit_message_caption(chat_id=self.chat.id,
|
||||
message_id=callback.message.message_id,
|
||||
caption=product.text(style="image",
|
||||
cart_qty=cart[callback.message.message_id][1]),
|
||||
caption=product.text(cart_qty=cart[callback.message.message_id][1]),
|
||||
parse_mode="HTML",
|
||||
reply_markup=product_inline_keyboard)
|
||||
# Create the cart summary
|
||||
|
@ -364,8 +363,7 @@ class ChatWorker(threading.Thread):
|
|||
else:
|
||||
self.bot.edit_message_caption(chat_id=self.chat.id,
|
||||
message_id=callback.message.message_id,
|
||||
caption=product.text(style="image",
|
||||
cart_qty=cart[callback.message.message_id][1]),
|
||||
caption=product.text(cart_qty=cart[callback.message.message_id][1]),
|
||||
parse_mode="HTML",
|
||||
reply_markup=product_inline_keyboard)
|
||||
# Create the cart summary
|
||||
|
@ -444,7 +442,7 @@ class ChatWorker(threading.Thread):
|
|||
orders = self.session.query(db.Order)\
|
||||
.filter(db.Order.user == self.user)\
|
||||
.order_by(db.Order.creation_date.desc())\
|
||||
.limit(5)\
|
||||
.limit(20)\
|
||||
.all()
|
||||
# Ensure there is at least one order to display
|
||||
if len(orders) == 0:
|
||||
|
@ -601,14 +599,14 @@ class ChatWorker(threading.Thread):
|
|||
keyboard.append([strings.menu_products])
|
||||
if self.admin.receive_orders:
|
||||
keyboard.append([strings.menu_orders])
|
||||
if self.admin.view_transactions:
|
||||
keyboard.append([strings.menu_transactions])
|
||||
if self.admin.create_transactions:
|
||||
keyboard.append([strings.menu_edit_credit])
|
||||
# Send the previously created keyboard to the user (ensuring it can be clicked only 1 time)
|
||||
self.bot.send_message(self.chat.id, strings.conversation_open_admin_menu,
|
||||
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
|
||||
# Wait for a reply from the user
|
||||
selection = self.__wait_for_specific_message([strings.menu_products, strings.menu_orders,
|
||||
strings.menu_user_mode])
|
||||
strings.menu_user_mode, strings.menu_edit_credit])
|
||||
# If the user has selected the Products option...
|
||||
if selection == strings.menu_products:
|
||||
# Open the products menu
|
||||
|
@ -617,6 +615,10 @@ class ChatWorker(threading.Thread):
|
|||
elif selection == strings.menu_orders:
|
||||
# Open the orders menu
|
||||
self.__orders_menu()
|
||||
# If the user has selected the Transactions option...
|
||||
elif selection == strings.menu_edit_credit:
|
||||
# Open the edit credit menu
|
||||
self.__create_transaction()
|
||||
# If the user has selected the User mode option...
|
||||
elif selection == strings.menu_user_mode:
|
||||
# Start the bot in user mode
|
||||
|
@ -862,6 +864,66 @@ class ChatWorker(threading.Thread):
|
|||
self.bot.send_message(order.user_id,
|
||||
strings.notification_order_refunded.format(order=order.get_text(self.session)))
|
||||
|
||||
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()
|
||||
# Create a list containing all the keyboard button strings
|
||||
keyboard_buttons = [[strings.menu_cancel]]
|
||||
# Add to the list all the users
|
||||
for user in users:
|
||||
keyboard_buttons.append([user.identifiable_str()])
|
||||
# TODO: handle more than 99 users
|
||||
# Create the keyboard
|
||||
keyboard = telegram.ReplyKeyboardMarkup(keyboard_buttons, one_time_keyboard=True)
|
||||
# Send the keyboard
|
||||
self.bot.send_message(self.chat.id, strings.conversation_admin_select_user, reply_markup=keyboard)
|
||||
# Wait for a reply
|
||||
reply = self.__wait_for_regex("user_([0-9]+)", cancellable=True)
|
||||
# Allow the cancellation of the operation
|
||||
if reply == strings.menu_cancel:
|
||||
return
|
||||
# Find the user in the database
|
||||
user = self.session.query(db.User).filter_by(user_id=int(reply)).one_or_none()
|
||||
# Ensure the user exists
|
||||
if not user:
|
||||
self.bot.send_message(self.chat.id, strings.error_user_does_not_exist)
|
||||
# Create an inline keyboard with a single cancel button
|
||||
cancel = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_cancel,
|
||||
callback_data="cmd_cancel")]])
|
||||
# Request from the user the amount of money to be credited manually
|
||||
self.bot.send_message(self.chat.id, strings.ask_credit, reply_markup=cancel)
|
||||
# Wait for an answer
|
||||
reply = self.__wait_for_regex(r"(-? ?[0-9]{1,3}(?:[.,][0-9]{1,2})?)", cancellable=True)
|
||||
# Allow the cancellation of the operation
|
||||
if isinstance(reply, CancelSignal):
|
||||
return
|
||||
# Convert the reply to a price object
|
||||
price = utils.Price(reply)
|
||||
# Ask the user for notes
|
||||
self.bot.send_message(self.chat.id, strings.ask_transaction_notes, reply_markup=cancel)
|
||||
# Wait for an answer
|
||||
reply = self.__wait_for_regex(r"(.*)", cancellable=True)
|
||||
# Allow the cancellation of the operation
|
||||
if isinstance(reply, CancelSignal):
|
||||
return
|
||||
# Create a new transaction
|
||||
transaction = db.Transaction(user=user,
|
||||
value=int(price),
|
||||
provider="Manual",
|
||||
notes=reply)
|
||||
self.session.add(transaction)
|
||||
# Change the user credit
|
||||
user.credit += int(price)
|
||||
# Commit the changes
|
||||
self.session.commit()
|
||||
# Notify the user of the credit/debit
|
||||
self.bot.send_message(user.user_id,
|
||||
strings.notification_transaction_created.format(transaction=str(transaction)),
|
||||
parse_mode="HTML")
|
||||
# Notify the admin of the success
|
||||
self.bot.send_message(self.chat.id, strings.success_transaction_created)
|
||||
|
||||
def __graceful_stop(self):
|
||||
"""Handle the graceful stop of the thread."""
|
||||
# Notify the user that the session has expired and remove the keyboard
|
||||
|
|
Loading…
Reference in a new issue