mirror of
https://github.com/Steffo99/greed.git
synced 2024-12-04 19:34:19 +00:00
I found this on my pc, I have no idea of what I was trying to do
This commit is contained in:
parent
087eb0d594
commit
dd686a4456
4 changed files with 138 additions and 117 deletions
|
@ -2,39 +2,44 @@ import sys
|
||||||
import os
|
import os
|
||||||
import configparser
|
import configparser
|
||||||
|
|
||||||
# Check if the config file exists, and create one if it doesn't
|
|
||||||
if not os.path.isfile("config/config.ini"):
|
def load_config(template_filename="config/template_config.ini",
|
||||||
|
config_filename="config/config.ini") -> configparser.ConfigParser:
|
||||||
|
# Check if the config file exists, and create one if it doesn't
|
||||||
|
if not os.path.isfile(config_filename):
|
||||||
# Open the template file and create the config file
|
# Open the template file and create the config file
|
||||||
with open("config/template_config.ini") as template_file, open("config/config.ini", "w") as config_file:
|
with open(template_filename) as template_file, open(config_filename, "w") as config_file:
|
||||||
# Copy the template file to the config file
|
# Copy the template file to the config file
|
||||||
config_file.write(template_file.read())
|
config_file.write(template_file.read())
|
||||||
|
|
||||||
with open("config/template_config.ini") as template_file:
|
with open(template_filename) as template_file:
|
||||||
# Find the template version number
|
# Find the template version number
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read_file(template_file)
|
config.read_file(template_file)
|
||||||
template_version = int(config["Config"]["version"])
|
template_version = int(config["Config"]["version"])
|
||||||
|
|
||||||
# Overwrite the template config with the values in the config
|
# Overwrite the template config with the values in the config
|
||||||
with open("config/config.ini") as config_file:
|
with open(config_filename) as config_file:
|
||||||
config.read_file(config_file)
|
config.read_file(config_file)
|
||||||
|
|
||||||
# Check if the file has been edited
|
# Check if the file has been edited
|
||||||
if config["Config"]["is_template"] == "yes":
|
if config["Config"]["is_template"] == "yes":
|
||||||
print("A config file has been created in config/config.ini.\n"
|
print("A config file has been created in config/config.ini.\n"
|
||||||
"Edit it with your configuration, set the is_template flag to false and restart this script.")
|
"Edit it with your configuration, set the is_template flag to false and restart this script.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Check if the version has changed from the template
|
# Check if the version has changed from the template
|
||||||
if template_version > int(config["Config"]["version"]):
|
if template_version > int(config["Config"]["version"]):
|
||||||
# Reset the is_template flag
|
# Reset the is_template flag
|
||||||
config["Config"]["is_template"] = "yes"
|
config["Config"]["is_template"] = "yes"
|
||||||
# Update the config version
|
# Update the config version
|
||||||
config["Config"]["version"] = str(template_version)
|
config["Config"]["version"] = str(template_version)
|
||||||
# Save the file
|
# Save the file
|
||||||
with open("config/config.ini", "w") as config_file:
|
with open(config_filename, "w") as config_file:
|
||||||
config.write(config_file)
|
config.write(config_file)
|
||||||
# Notify the user and quit
|
# Notify the user and quit
|
||||||
print("The config file in config/config.ini has been updated.\n"
|
print("The config file in config/config.ini has been updated.\n"
|
||||||
"Edit it with the new required data, set the is_template flag to true and restart this script.")
|
"Edit it with the new required data, set the is_template flag to true and restart this script.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
9
core.py
9
core.py
|
@ -13,8 +13,11 @@ def main():
|
||||||
# Rename the main thread for presentation purposes
|
# Rename the main thread for presentation purposes
|
||||||
threading.current_thread().name = "Core"
|
threading.current_thread().name = "Core"
|
||||||
|
|
||||||
|
# Load the config
|
||||||
|
config = configloader.load_config()
|
||||||
|
|
||||||
# Create a bot instance
|
# Create a bot instance
|
||||||
bot = utils.DuckBot(configloader.config["Telegram"]["token"])
|
bot = utils.DuckBot(config["Telegram"]["token"])
|
||||||
|
|
||||||
# Test the specified token
|
# Test the specified token
|
||||||
try:
|
try:
|
||||||
|
@ -38,7 +41,7 @@ def main():
|
||||||
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
|
||||||
updates = bot.get_updates(offset=next_update,
|
updates = bot.get_updates(offset=next_update,
|
||||||
timeout=int(configloader.config["Telegram"]["long_polling_timeout"]))
|
timeout=int(config["Telegram"]["long_polling_timeout"]))
|
||||||
# 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...
|
||||||
|
@ -57,7 +60,7 @@ def main():
|
||||||
if old_worker:
|
if old_worker:
|
||||||
old_worker.stop("request")
|
old_worker.stop("request")
|
||||||
# Initialize a new worker for the chat
|
# Initialize a new worker for the chat
|
||||||
new_worker = worker.ChatWorker(bot, update.message.chat)
|
new_worker = worker.ChatWorker(bot=bot, chat=update.message.chat, config=config)
|
||||||
# Start the worker
|
# Start the worker
|
||||||
new_worker.start()
|
new_worker.start()
|
||||||
# Store the worker in the dictionary
|
# Store the worker in the dictionary
|
||||||
|
|
61
utils.py
61
utils.py
|
@ -1,40 +1,31 @@
|
||||||
import telegram
|
import telegram
|
||||||
import telegram.error
|
import telegram.error
|
||||||
import time
|
import time
|
||||||
from configloader import config
|
|
||||||
from strings import currency_format_string, currency_symbol
|
from strings import currency_format_string, currency_symbol
|
||||||
import typing
|
import typing
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import strings
|
import strings
|
||||||
|
|
||||||
if config["Error Reporting"]["sentry_token"] != \
|
|
||||||
"https://00000000000000000000000000000000:00000000000000000000000000000000@sentry.io/0000000":
|
|
||||||
import raven
|
|
||||||
|
|
||||||
sentry_client = raven.Client(config["Error Reporting"]["sentry_token"],
|
|
||||||
release=raven.fetch_git_sha(os.path.dirname(__file__)),
|
|
||||||
environment="Dev" if __debug__ else "Prod")
|
|
||||||
else:
|
|
||||||
sentry_client = None
|
|
||||||
|
|
||||||
|
|
||||||
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"], exp: int):
|
||||||
if isinstance(value, int):
|
if isinstance(value, int):
|
||||||
# Keep the value as it is
|
# Keep the value as it is
|
||||||
self.value = int(value)
|
self.value = int(value)
|
||||||
elif isinstance(value, float):
|
elif isinstance(value, float):
|
||||||
# Convert the value to minimum units
|
# Convert the value to minimum units
|
||||||
self.value = int(value * (10 ** int(config["Payments"]["currency_exp"])))
|
self.value = int(value * (10 ** exp))
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
# Remove decimal points, then cast to int
|
# Remove decimal points, then cast to int
|
||||||
self.value = int(float(value.replace(",", ".")) * (10 ** int(config["Payments"]["currency_exp"])))
|
self.value = int(float(value.replace(",", ".")) * (10 ** exp))
|
||||||
elif isinstance(value, Price):
|
elif isinstance(value, Price):
|
||||||
# Copy self
|
# Copy self
|
||||||
self.value = value.value
|
self.value = value.value
|
||||||
|
else:
|
||||||
|
raise TypeError("Value is of an unsupported type")
|
||||||
|
self.exp: int = exp
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Price of value {self.value}>"
|
return f"<Price of value {self.value}>"
|
||||||
|
@ -42,57 +33,69 @@ class Price:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return currency_format_string.format(symbol=currency_symbol,
|
return currency_format_string.format(symbol=currency_symbol,
|
||||||
value="{0:.2f}".format(
|
value="{0:.2f}".format(
|
||||||
self.value / (10 ** int(config["Payments"]["currency_exp"]))))
|
self.value / (10 ** self.exp)))
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def __float__(self):
|
def __float__(self):
|
||||||
return self.value / (10 ** int(config["Payments"]["currency_exp"]))
|
return self.value / (10 ** self.exp)
|
||||||
|
|
||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return self.value >= Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return self.value >= Price(other, self.exp).value
|
||||||
|
|
||||||
def __le__(self, other):
|
def __le__(self, other):
|
||||||
return self.value <= Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return self.value <= Price(other, self.exp).value
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.value == Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return self.value == Price(other, self.exp).value
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
return self.value > Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return self.value > Price(other, self.exp).value
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
return self.value < Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return self.value < Price(other, self.exp).value
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return Price(self.value + Price(other).value)
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return Price(self.value + Price(other, self.exp).value, self.exp)
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
return Price(self.value - Price(other).value)
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return Price(self.value - Price(other, self.exp).value, self.exp)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return Price(int(self.value * other))
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return Price(int(self.value * other), self.exp)
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
def __floordiv__(self, other):
|
||||||
return Price(int(self.value // other))
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return Price(int(self.value // other), self.exp)
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other):
|
||||||
return self.__add__(other)
|
return self.__add__(other)
|
||||||
|
|
||||||
def __rsub__(self, other):
|
def __rsub__(self, other):
|
||||||
return Price(Price(other).value - self.value)
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
return Price(Price(other, self.exp).value - self.value, self.exp)
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other):
|
||||||
|
|
||||||
return self.__mul__(other)
|
return self.__mul__(other)
|
||||||
|
|
||||||
def __iadd__(self, other):
|
def __iadd__(self, other):
|
||||||
self.value += Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
self.value += Price(other, self.exp).value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __isub__(self, other):
|
def __isub__(self, other):
|
||||||
self.value -= Price(other).value
|
# Assuming currency exp is the same for the compared prices
|
||||||
|
self.value -= Price(other, self.exp).value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __imul__(self, other):
|
def __imul__(self, other):
|
||||||
|
|
112
worker.py
112
worker.py
|
@ -4,7 +4,7 @@ import uuid
|
||||||
import datetime
|
import datetime
|
||||||
import telegram
|
import telegram
|
||||||
import strings
|
import strings
|
||||||
import configloader
|
import configparser
|
||||||
import sys
|
import sys
|
||||||
import queue as queuem
|
import queue as queuem
|
||||||
import database as db
|
import database as db
|
||||||
|
@ -18,7 +18,7 @@ import requests
|
||||||
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."""
|
||||||
|
|
||||||
def __init__(self, reason: str=""):
|
def __init__(self, reason: str = ""):
|
||||||
self.reason = reason
|
self.reason = reason
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,12 +30,20 @@ class CancelSignal:
|
||||||
class ChatWorker(threading.Thread):
|
class ChatWorker(threading.Thread):
|
||||||
"""A worker for a single conversation. A new one is created every time the /start command is sent."""
|
"""A worker for a single conversation. A new one is created every time the /start command is sent."""
|
||||||
|
|
||||||
def __init__(self, bot: utils.DuckBot, chat: telegram.Chat, *args, **kwargs):
|
def __init__(self,
|
||||||
|
bot: utils.DuckBot,
|
||||||
|
chat: telegram.Chat,
|
||||||
|
config: configparser.ConfigParser,
|
||||||
|
*args,
|
||||||
|
**kwargs):
|
||||||
# Initialize the thread
|
# Initialize the thread
|
||||||
super().__init__(name=f"Worker {chat.id}", *args, **kwargs)
|
super().__init__(name=f"Worker {chat.id}", *args, **kwargs)
|
||||||
# Store the bot and chat info inside the class
|
# Store the bot, chat info and config inside the class
|
||||||
self.bot: utils.DuckBot = bot
|
self.bot: utils.DuckBot = bot
|
||||||
self.chat: telegram.Chat = chat
|
self.chat: telegram.Chat = chat
|
||||||
|
self.config: configparser.ConfigParser = config
|
||||||
|
# A shortcut to currency_exp
|
||||||
|
self._exp: int = int(config["Payments"]["currency_exp"])
|
||||||
# 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
|
||||||
|
@ -46,10 +54,10 @@ class ChatWorker(threading.Thread):
|
||||||
# The current active invoice payload; reject all invoices with a different payload
|
# The current active invoice payload; reject all invoices with a different payload
|
||||||
self.invoice_payload = None
|
self.invoice_payload = None
|
||||||
# The Sentry client for reporting errors encountered by the user
|
# The Sentry client for reporting errors encountered by the user
|
||||||
if configloader.config["Error Reporting"]["sentry_token"] != \
|
if self.config["Error Reporting"]["sentry_token"] != \
|
||||||
"https://00000000000000000000000000000000:00000000000000000000000000000000@sentry.io/0000000":
|
"https://00000000000000000000000000000000:00000000000000000000000000000000@sentry.io/0000000":
|
||||||
import raven
|
import raven
|
||||||
self.sentry_client = raven.Client(configloader.config["Error Reporting"]["sentry_token"],
|
self.sentry_client = raven.Client(self.config["Error Reporting"]["sentry_token"],
|
||||||
release=raven.fetch_git_sha(os.path.dirname(__file__)),
|
release=raven.fetch_git_sha(os.path.dirname(__file__)),
|
||||||
environment="Dev" if __debug__ else "Prod")
|
environment="Dev" if __debug__ else "Prod")
|
||||||
else:
|
else:
|
||||||
|
@ -110,7 +118,7 @@ class ChatWorker(threading.Thread):
|
||||||
if self.sentry_client is not None:
|
if self.sentry_client is not None:
|
||||||
self.sentry_client.captureException()
|
self.sentry_client.captureException()
|
||||||
|
|
||||||
def stop(self, reason: str=""):
|
def stop(self, reason: str = ""):
|
||||||
"""Gracefully stop the worker process"""
|
"""Gracefully stop the worker process"""
|
||||||
# Send a stop message to the thread
|
# Send a stop message to the thread
|
||||||
self.queue.put(StopSignal(reason))
|
self.queue.put(StopSignal(reason))
|
||||||
|
@ -130,7 +138,7 @@ class ChatWorker(threading.Thread):
|
||||||
If a stop signal is sent, try to gracefully stop the thread."""
|
If a stop signal is sent, try to gracefully stop the thread."""
|
||||||
# Pop data from the queue
|
# Pop data from the queue
|
||||||
try:
|
try:
|
||||||
data = self.queue.get(timeout=int(configloader.config["Telegram"]["conversation_timeout"]))
|
data = self.queue.get(timeout=int(self.config["Telegram"]["conversation_timeout"]))
|
||||||
except queuem.Empty:
|
except queuem.Empty:
|
||||||
# If the conversation times out, gracefully stop the thread
|
# If the conversation times out, gracefully stop the thread
|
||||||
self.__graceful_stop(StopSignal("timeout"))
|
self.__graceful_stop(StopSignal("timeout"))
|
||||||
|
@ -143,7 +151,7 @@ class ChatWorker(threading.Thread):
|
||||||
|
|
||||||
def __wait_for_specific_message(self,
|
def __wait_for_specific_message(self,
|
||||||
items: typing.List[str],
|
items: typing.List[str],
|
||||||
cancellable: bool=False) -> typing.Union[str, CancelSignal]:
|
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
|
||||||
|
@ -168,7 +176,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
|
||||||
|
@ -192,7 +200,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) -> 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:
|
||||||
|
@ -222,7 +230,8 @@ 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) -> typing.Union[
|
||||||
|
typing.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
|
||||||
|
@ -240,7 +249,7 @@ class ChatWorker(threading.Thread):
|
||||||
# Return the photo array
|
# Return the photo array
|
||||||
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]:
|
-> typing.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:
|
||||||
|
@ -298,7 +307,8 @@ class ChatWorker(threading.Thread):
|
||||||
[telegram.KeyboardButton(strings.menu_help), telegram.KeyboardButton(strings.menu_bot_info)]]
|
[telegram.KeyboardButton(strings.menu_help), telegram.KeyboardButton(strings.menu_bot_info)]]
|
||||||
# Send the previously created keyboard to the user (ensuring it can be clicked only 1 time)
|
# Send the previously created keyboard to the user (ensuring it can be clicked only 1 time)
|
||||||
self.bot.send_message(self.chat.id,
|
self.bot.send_message(self.chat.id,
|
||||||
strings.conversation_open_user_menu.format(credit=utils.Price(self.user.credit)),
|
strings.conversation_open_user_menu.format(credit=utils.Price(self.user.credit,
|
||||||
|
self._exp)),
|
||||||
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
|
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
|
||||||
# Wait for a reply from the user
|
# Wait for a reply from the user
|
||||||
selection = self.__wait_for_specific_message([strings.menu_order, strings.menu_order_status,
|
selection = self.__wait_for_specific_message([strings.menu_order, strings.menu_order_status,
|
||||||
|
@ -404,7 +414,7 @@ class ChatWorker(threading.Thread):
|
||||||
reply_markup=product_inline_keyboard)
|
reply_markup=product_inline_keyboard)
|
||||||
# Create the cart summary
|
# Create the cart summary
|
||||||
product_list = ""
|
product_list = ""
|
||||||
total_cost = utils.Price(0)
|
total_cost = utils.Price(0, self._exp)
|
||||||
for product_id in cart:
|
for product_id in cart:
|
||||||
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"
|
||||||
|
@ -452,7 +462,7 @@ class ChatWorker(threading.Thread):
|
||||||
reply_markup=product_inline_keyboard)
|
reply_markup=product_inline_keyboard)
|
||||||
# Create the cart summary
|
# Create the cart summary
|
||||||
product_list = ""
|
product_list = ""
|
||||||
total_cost = utils.Price(0)
|
total_cost = utils.Price(0, self._exp)
|
||||||
for product_id in cart:
|
for product_id in cart:
|
||||||
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"
|
||||||
|
@ -524,10 +534,10 @@ class ChatWorker(threading.Thread):
|
||||||
def __order_status(self):
|
def __order_status(self):
|
||||||
"""Display the status of the sent orders."""
|
"""Display the status of the sent orders."""
|
||||||
# Find the latest orders
|
# Find the latest orders
|
||||||
orders = self.session.query(db.Order)\
|
orders = self.session.query(db.Order) \
|
||||||
.filter(db.Order.user == self.user)\
|
.filter(db.Order.user == self.user) \
|
||||||
.order_by(db.Order.creation_date.desc())\
|
.order_by(db.Order.creation_date.desc()) \
|
||||||
.limit(20)\
|
.limit(20) \
|
||||||
.all()
|
.all()
|
||||||
# Ensure there is at least one order to display
|
# Ensure there is at least one order to display
|
||||||
if len(orders) == 0:
|
if len(orders) == 0:
|
||||||
|
@ -545,7 +555,7 @@ class ChatWorker(threading.Thread):
|
||||||
# Cash
|
# Cash
|
||||||
keyboard.append([telegram.KeyboardButton(strings.menu_cash)])
|
keyboard.append([telegram.KeyboardButton(strings.menu_cash)])
|
||||||
# Telegram Payments
|
# Telegram Payments
|
||||||
if configloader.config["Credit Card"]["credit_card_token"] != "":
|
if self.config["Credit Card"]["credit_card_token"] != "":
|
||||||
keyboard.append([telegram.KeyboardButton(strings.menu_credit_card)])
|
keyboard.append([telegram.KeyboardButton(strings.menu_credit_card)])
|
||||||
# Keyboard: go back to the previous menu
|
# Keyboard: go back to the previous menu
|
||||||
keyboard.append([telegram.KeyboardButton(strings.menu_cancel)])
|
keyboard.append([telegram.KeyboardButton(strings.menu_cancel)])
|
||||||
|
@ -571,10 +581,10 @@ class ChatWorker(threading.Thread):
|
||||||
def __add_credit_cc(self):
|
def __add_credit_cc(self):
|
||||||
"""Add money to the wallet through a credit card payment."""
|
"""Add money to the wallet through a credit card payment."""
|
||||||
# Create a keyboard to be sent later
|
# Create a keyboard to be sent later
|
||||||
keyboard = [[telegram.KeyboardButton(str(utils.Price("10.00")))],
|
keyboard = [[telegram.KeyboardButton(str(utils.Price("10.00", self._exp)))],
|
||||||
[telegram.KeyboardButton(str(utils.Price("25.00")))],
|
[telegram.KeyboardButton(str(utils.Price("25.00", self._exp)))],
|
||||||
[telegram.KeyboardButton(str(utils.Price("50.00")))],
|
[telegram.KeyboardButton(str(utils.Price("50.00", self._exp)))],
|
||||||
[telegram.KeyboardButton(str(utils.Price("100.00")))],
|
[telegram.KeyboardButton(str(utils.Price("100.00", self._exp)))],
|
||||||
[telegram.KeyboardButton(strings.menu_cancel)]]
|
[telegram.KeyboardButton(strings.menu_cancel)]]
|
||||||
# Boolean variable to check if the user has cancelled the action
|
# Boolean variable to check if the user has cancelled the action
|
||||||
cancelled = False
|
cancelled = False
|
||||||
|
@ -592,17 +602,17 @@ class ChatWorker(threading.Thread):
|
||||||
cancelled = True
|
cancelled = True
|
||||||
continue
|
continue
|
||||||
# Convert the amount to an integer
|
# Convert the amount to an integer
|
||||||
value = utils.Price(selection)
|
value = utils.Price(selection, self._exp)
|
||||||
# Ensure the amount is within the range
|
# Ensure the amount is within the range
|
||||||
if value > utils.Price(int(configloader.config["Credit Card"]["max_amount"])):
|
if value > utils.Price(int(self.config["Credit Card"]["max_amount"]), self._exp):
|
||||||
self.bot.send_message(self.chat.id,
|
self.bot.send_message(self.chat.id,
|
||||||
strings.error_payment_amount_over_max.format(
|
strings.error_payment_amount_over_max.format(
|
||||||
max_amount=utils.Price(configloader.config["Payments"]["max_amount"])))
|
max_amount=utils.Price(self.config["Payments"]["max_amount"], self._exp)))
|
||||||
continue
|
continue
|
||||||
elif value < utils.Price(int(configloader.config["Credit Card"]["min_amount"])):
|
elif value < utils.Price(int(self.config["Credit Card"]["min_amount"]), self._exp):
|
||||||
self.bot.send_message(self.chat.id,
|
self.bot.send_message(self.chat.id,
|
||||||
strings.error_payment_amount_under_min.format(
|
strings.error_payment_amount_under_min.format(
|
||||||
min_amount=utils.Price(configloader.config["Payments"]["min_amount"])))
|
min_amount=utils.Price(self.config["Payments"]["min_amount"], self._exp)))
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
# If the user cancelled the action...
|
# If the user cancelled the action...
|
||||||
|
@ -614,8 +624,8 @@ class ChatWorker(threading.Thread):
|
||||||
# Create the price array
|
# Create the price array
|
||||||
prices = [telegram.LabeledPrice(label=strings.payment_invoice_label, amount=int(value))]
|
prices = [telegram.LabeledPrice(label=strings.payment_invoice_label, amount=int(value))]
|
||||||
# If the user has to pay a fee when using the credit card, add it to the prices list
|
# If the user has to pay a fee when using the credit card, add it to the prices list
|
||||||
fee_percentage = float(configloader.config["Credit Card"]["fee_percentage"]) / 100
|
fee_percentage = float(self.config["Credit Card"]["fee_percentage"]) / 100
|
||||||
fee_fixed = int(configloader.config["Credit Card"]["fee_fixed"])
|
fee_fixed = int(self.config["Credit Card"]["fee_fixed"])
|
||||||
total_fee = value * fee_percentage + fee_fixed
|
total_fee = value * fee_percentage + fee_fixed
|
||||||
if total_fee > 0:
|
if total_fee > 0:
|
||||||
prices.append(telegram.LabeledPrice(label=strings.payment_invoice_fee_label, amount=int(total_fee)))
|
prices.append(telegram.LabeledPrice(label=strings.payment_invoice_fee_label, amount=int(total_fee)))
|
||||||
|
@ -631,13 +641,13 @@ class ChatWorker(threading.Thread):
|
||||||
title=strings.payment_invoice_title,
|
title=strings.payment_invoice_title,
|
||||||
description=strings.payment_invoice_description.format(amount=str(value)),
|
description=strings.payment_invoice_description.format(amount=str(value)),
|
||||||
payload=self.invoice_payload,
|
payload=self.invoice_payload,
|
||||||
provider_token=configloader.config["Credit Card"]["credit_card_token"],
|
provider_token=self.config["Credit Card"]["credit_card_token"],
|
||||||
start_parameter="tempdeeplink",
|
start_parameter="tempdeeplink",
|
||||||
currency=configloader.config["Payments"]["currency"],
|
currency=self.config["Payments"]["currency"],
|
||||||
prices=prices,
|
prices=prices,
|
||||||
need_name=configloader.config["Credit Card"]["name_required"] == "yes",
|
need_name=self.config["Credit Card"]["name_required"] == "yes",
|
||||||
need_email=configloader.config["Credit Card"]["email_required"] == "yes",
|
need_email=self.config["Credit Card"]["email_required"] == "yes",
|
||||||
need_phone_number=configloader.config["Credit Card"]["phone_required"] == "yes",
|
need_phone_number=self.config["Credit Card"]["phone_required"] == "yes",
|
||||||
reply_markup=inline_keyboard)
|
reply_markup=inline_keyboard)
|
||||||
# Wait for the invoice
|
# Wait for the invoice
|
||||||
precheckoutquery = self.__wait_for_precheckoutquery(cancellable=True)
|
precheckoutquery = self.__wait_for_precheckoutquery(cancellable=True)
|
||||||
|
@ -762,7 +772,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: typing.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,
|
||||||
|
@ -778,7 +788,7 @@ class ChatWorker(threading.Thread):
|
||||||
# Wait for an answer
|
# Wait for an answer
|
||||||
name = self.__wait_for_regex(r"(.*)", cancellable=bool(product))
|
name = self.__wait_for_regex(r"(.*)", cancellable=bool(product))
|
||||||
# Ensure a product with that name doesn't already exist
|
# Ensure a product with that name doesn't already exist
|
||||||
if (product and isinstance(name, CancelSignal)) or\
|
if (product and isinstance(name, CancelSignal)) or \
|
||||||
self.session.query(db.Product).filter_by(name=name, deleted=False).one_or_none() in [None, product]:
|
self.session.query(db.Product).filter_by(name=name, deleted=False).one_or_none() in [None, product]:
|
||||||
# Exit the loop
|
# Exit the loop
|
||||||
break
|
break
|
||||||
|
@ -799,7 +809,7 @@ class ChatWorker(threading.Thread):
|
||||||
if product:
|
if product:
|
||||||
self.bot.send_message(self.chat.id,
|
self.bot.send_message(self.chat.id,
|
||||||
strings.edit_current_value.format(
|
strings.edit_current_value.format(
|
||||||
value=(str(utils.Price(product.price))
|
value=(str(utils.Price(product.price, self._exp))
|
||||||
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
|
||||||
|
@ -811,7 +821,7 @@ class ChatWorker(threading.Thread):
|
||||||
elif price.lower() == "x":
|
elif price.lower() == "x":
|
||||||
price = None
|
price = None
|
||||||
else:
|
else:
|
||||||
price = utils.Price(price)
|
price = utils.Price(price, self._exp)
|
||||||
# Ask for the product image
|
# Ask for the product image
|
||||||
self.bot.send_message(self.chat.id, strings.ask_product_image, reply_markup=cancel)
|
self.bot.send_message(self.chat.id, strings.ask_product_image, reply_markup=cancel)
|
||||||
# Wait for an answer
|
# Wait for an answer
|
||||||
|
@ -892,10 +902,10 @@ class ChatWorker(threading.Thread):
|
||||||
[telegram.InlineKeyboardButton(strings.menu_refund,
|
[telegram.InlineKeyboardButton(strings.menu_refund,
|
||||||
callback_data="order_refund")]])
|
callback_data="order_refund")]])
|
||||||
# Display the past pending orders
|
# Display the past pending orders
|
||||||
orders = self.session.query(db.Order)\
|
orders = self.session.query(db.Order) \
|
||||||
.filter_by(delivery_date=None, refund_date=None)\
|
.filter_by(delivery_date=None, refund_date=None) \
|
||||||
.join(db.Transaction)\
|
.join(db.Transaction) \
|
||||||
.join(db.User)\
|
.join(db.User) \
|
||||||
.all()
|
.all()
|
||||||
# Create a message for every one of them
|
# Create a message for every one of them
|
||||||
for order in orders:
|
for order in orders:
|
||||||
|
@ -1043,10 +1053,10 @@ class ChatWorker(threading.Thread):
|
||||||
# Loop used to move between pages
|
# Loop used to move between pages
|
||||||
while True:
|
while True:
|
||||||
# Retrieve the 10 transactions in that page
|
# Retrieve the 10 transactions in that page
|
||||||
transactions = self.session.query(db.Transaction)\
|
transactions = self.session.query(db.Transaction) \
|
||||||
.order_by(db.Transaction.transaction_id.desc())\
|
.order_by(db.Transaction.transaction_id.desc()) \
|
||||||
.limit(10)\
|
.limit(10) \
|
||||||
.offset(10 * page)\
|
.offset(10 * page) \
|
||||||
.all()
|
.all()
|
||||||
# Create a list to be converted in inline keyboard markup
|
# Create a list to be converted in inline keyboard markup
|
||||||
inline_keyboard_list = [[]]
|
inline_keyboard_list = [[]]
|
||||||
|
@ -1068,7 +1078,7 @@ class ChatWorker(threading.Thread):
|
||||||
inline_keyboard = telegram.InlineKeyboardMarkup(inline_keyboard_list)
|
inline_keyboard = telegram.InlineKeyboardMarkup(inline_keyboard_list)
|
||||||
# Create the message text
|
# Create the message text
|
||||||
transactions_string = "\n".join([str(transaction) for transaction in transactions])
|
transactions_string = "\n".join([str(transaction) for transaction in transactions])
|
||||||
text = strings.transactions_page.format(page=page+1,
|
text = strings.transactions_page.format(page=page + 1,
|
||||||
transactions=transactions_string)
|
transactions=transactions_string)
|
||||||
# Update the previously sent message
|
# Update the previously sent message
|
||||||
self.bot.edit_message_text(chat_id=self.chat.id, message_id=message.message_id, text=text,
|
self.bot.edit_message_text(chat_id=self.chat.id, message_id=message.message_id, text=text,
|
||||||
|
@ -1126,7 +1136,7 @@ class ChatWorker(threading.Thread):
|
||||||
# Reopen the file for reading
|
# Reopen the file for reading
|
||||||
with open(f"transactions_{self.chat.id}.csv") as file:
|
with open(f"transactions_{self.chat.id}.csv") as file:
|
||||||
# Send the file via a manual request to Telegram
|
# Send the file via a manual request to Telegram
|
||||||
requests.post(f"https://api.telegram.org/bot{configloader.config['Telegram']['token']}/sendDocument",
|
requests.post(f"https://api.telegram.org/bot{self.config['Telegram']['token']}/sendDocument",
|
||||||
files={"document": file},
|
files={"document": file},
|
||||||
params={"chat_id": self.chat.id,
|
params={"chat_id": self.chat.id,
|
||||||
"parse_mode": "HTML"})
|
"parse_mode": "HTML"})
|
||||||
|
|
Loading…
Reference in a new issue