mirror of
https://github.com/Steffo99/greed.git
synced 2024-11-22 14:04:18 +00:00
Start working on the code for the bot
This commit is contained in:
parent
d4febea186
commit
5f04a1ffe9
4 changed files with 99 additions and 15 deletions
2
core.py
2
core.py
|
@ -75,7 +75,7 @@ def main():
|
||||||
# Skip the update
|
# Skip the update
|
||||||
continue
|
continue
|
||||||
# If the message is a start command...
|
# If the message is a start command...
|
||||||
if update.message.text == "/start":
|
if update.message.text is not None and update.message.text == "/start":
|
||||||
# Check if a worker already exists for that chat
|
# Check if a worker already exists for that chat
|
||||||
old_worker = chat_workers.get(update.message.chat.id)
|
old_worker = chat_workers.get(update.message.chat.id)
|
||||||
# If it exists, gracefully stop the worker
|
# If it exists, gracefully stop the worker
|
||||||
|
|
10
database.py
10
database.py
|
@ -33,14 +33,14 @@ class User(TableDeclarativeBase):
|
||||||
# Extra table parameters
|
# Extra table parameters
|
||||||
__tablename__ = "users"
|
__tablename__ = "users"
|
||||||
|
|
||||||
def __init__(self, telegram_user: telegram.User, **kwargs):
|
def __init__(self, telegram_chat: telegram.Chat, **kwargs):
|
||||||
# Initialize the super
|
# Initialize the super
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
# Get the data from telegram
|
# Get the data from telegram
|
||||||
self.id = telegram_user.id
|
self.user_id = telegram_chat.id
|
||||||
self.first_name = telegram_user.first_name
|
self.first_name = telegram_chat.first_name
|
||||||
self.last_name = telegram_user.last_name
|
self.last_name = telegram_chat.last_name
|
||||||
self.username = telegram_user.username
|
self.username = telegram_chat.username
|
||||||
# The starting wallet value is 0
|
# The starting wallet value is 0
|
||||||
self.credit = decimal.Decimal("0")
|
self.credit = decimal.Decimal("0")
|
||||||
|
|
||||||
|
|
16
strings.py
16
strings.py
|
@ -15,10 +15,26 @@ in_stock_format_string = "{quantity} disponibili"
|
||||||
conversation_after_start = "Ciao!\n" \
|
conversation_after_start = "Ciao!\n" \
|
||||||
"Benvenuto su greed!"
|
"Benvenuto su greed!"
|
||||||
|
|
||||||
|
# Answer: to send an inline keyboard you need to send a message with it
|
||||||
|
conversation_open_user_menu = "Allora, {username}, cosa vorresti fare?"
|
||||||
|
|
||||||
# Notification: the conversation has expired
|
# Notification: the conversation has expired
|
||||||
conversation_expired = "🕐 Il bot non ha ricevuto messaggi per un po' di tempo, quindi ha chiuso la conversazione.\n" \
|
conversation_expired = "🕐 Il bot non ha ricevuto messaggi per un po' di tempo, quindi ha chiuso la conversazione.\n" \
|
||||||
"Per riavviarne una nuova, invia il comando /start."
|
"Per riavviarne una nuova, invia il comando /start."
|
||||||
|
|
||||||
|
# User menu: order
|
||||||
|
menu_order = "🛍 Ordina"
|
||||||
|
|
||||||
|
|
||||||
|
# User menu: order status
|
||||||
|
menu_order_status = "❓ Stato ordini"
|
||||||
|
|
||||||
|
# User menu: add credit
|
||||||
|
menu_add_credit = "💵 Ricarica"
|
||||||
|
|
||||||
|
# User menu: bot info
|
||||||
|
menu_info = "ℹ️ Informazioni sul bot"
|
||||||
|
|
||||||
# Error: message received not in a private chat
|
# Error: message received not in a private chat
|
||||||
error_nonprivate_chat = "⚠️ Questo bot funziona solo in chat private."
|
error_nonprivate_chat = "⚠️ Questo bot funziona solo in chat private."
|
||||||
|
|
||||||
|
|
86
worker.py
86
worker.py
|
@ -1,9 +1,11 @@
|
||||||
import threading
|
import threading
|
||||||
|
import typing
|
||||||
import telegram
|
import telegram
|
||||||
import strings
|
import strings
|
||||||
import configloader
|
import configloader
|
||||||
import sys
|
import sys
|
||||||
import queue as queuem
|
import queue as queuem
|
||||||
|
import database as db
|
||||||
|
|
||||||
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."""
|
||||||
|
@ -21,6 +23,11 @@ class ChatWorker(threading.Thread):
|
||||||
# Store the bot and chat info inside the class
|
# Store the bot and chat info inside the class
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.chat = chat
|
self.chat = chat
|
||||||
|
# Open a new database session
|
||||||
|
self.session = db.Session()
|
||||||
|
# Get the user db data from the users and admin tables
|
||||||
|
self.user = self.session.query(db.User).filter(db.User.user_id == self.chat.id).one_or_none()
|
||||||
|
self.admin = self.session.query(db.Admin).filter(db.Admin.user_id == self.chat.id).one_or_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()
|
||||||
|
|
||||||
|
@ -29,11 +36,20 @@ class ChatWorker(threading.Thread):
|
||||||
# TODO: catch all the possible exceptions
|
# 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)
|
||||||
# TODO: Send a command list or something
|
# If the user isn't registered, create a new record and add it to the db
|
||||||
while True:
|
if self.user is None:
|
||||||
# For now, echo the sent message
|
# Create the new record
|
||||||
update = self._receive_next_update()
|
self.user = db.User(self.chat)
|
||||||
self.bot.send_message(self.chat.id, f"{threading.current_thread().name} {update.message.text}")
|
# Add the new record to the db
|
||||||
|
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:
|
||||||
|
self.__admin_menu()
|
||||||
|
|
||||||
def stop(self, reason: str=""):
|
def stop(self, reason: str=""):
|
||||||
"""Gracefully stop the worker process"""
|
"""Gracefully stop the worker process"""
|
||||||
|
@ -42,7 +58,7 @@ class ChatWorker(threading.Thread):
|
||||||
# Wait for the thread to stop
|
# Wait for the thread to stop
|
||||||
self.join()
|
self.join()
|
||||||
|
|
||||||
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.
|
||||||
If a stop signal is sent, try to gracefully stop the thread."""
|
If a stop signal is sent, try to gracefully stop the thread."""
|
||||||
|
@ -51,17 +67,69 @@ class ChatWorker(threading.Thread):
|
||||||
data = self.queue.get(timeout=int(configloader.config["Telegram"]["conversation_timeout"]))
|
data = self.queue.get(timeout=int(configloader.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()
|
self.__graceful_stop()
|
||||||
# Check if the data is a stop signal instance
|
# Check if the data is a stop signal instance
|
||||||
if isinstance(data, StopSignal):
|
if isinstance(data, StopSignal):
|
||||||
# Gracefully stop the process
|
# Gracefully stop the process
|
||||||
self._graceful_stop()
|
self.__graceful_stop()
|
||||||
# Return the received update
|
# Return the received update
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _graceful_stop(self):
|
def __wait_for_specific_message(self, items:typing.List[str]) -> str:
|
||||||
|
"""Continue getting updates until until one of the strings contained in the list is received as a message."""
|
||||||
|
while True:
|
||||||
|
# Get the next update
|
||||||
|
update = self.__receive_next_update()
|
||||||
|
# Ensure the update contains a message
|
||||||
|
if update.message is None:
|
||||||
|
continue
|
||||||
|
# Ensure the message contains text
|
||||||
|
if update.message.text is None:
|
||||||
|
continue
|
||||||
|
# Check if the message is contained in the list
|
||||||
|
if update.message.text not in items:
|
||||||
|
continue
|
||||||
|
# Return the message text
|
||||||
|
return update.message.text
|
||||||
|
|
||||||
|
def __user_menu(self):
|
||||||
|
"""Function called from the run method when the user is not an administrator.
|
||||||
|
Normal bot actions should be placed here."""
|
||||||
|
# Create a keyboard with the user main menu
|
||||||
|
keyboard = [[telegram.KeyboardButton(strings.menu_order)],
|
||||||
|
[telegram.KeyboardButton(strings.menu_order_status)],
|
||||||
|
[telegram.KeyboardButton(strings.menu_add_credit)],
|
||||||
|
[telegram.KeyboardButton(strings.menu_info)]]
|
||||||
|
# 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_user_menu.format(username=str(self.user)),
|
||||||
|
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
|
||||||
|
# Wait for a reply from the user
|
||||||
|
# TODO: change this
|
||||||
|
selection = self.__wait_for_specific_message([strings.menu_order, strings.menu_order_status,
|
||||||
|
strings.menu_add_credit, strings.menu_info])
|
||||||
|
# If the user has selected the Order option...
|
||||||
|
if selection == strings.menu_order:
|
||||||
|
...
|
||||||
|
# If the user has selected the Order Status option...
|
||||||
|
elif selection == strings.menu_order_status:
|
||||||
|
...
|
||||||
|
# If the user has selected the Add Credit option...
|
||||||
|
elif selection == strings.menu_add_credit:
|
||||||
|
...
|
||||||
|
# If the user has selected the Bot Info option...
|
||||||
|
elif selection == strings.menu_info:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def __admin_menu(self):
|
||||||
|
"""Function called from the run method when the user is an administrator.
|
||||||
|
Administrative bot actions should be placed here."""
|
||||||
|
self.bot.send_message(self.chat.id, "Sei un Amministralol")
|
||||||
|
|
||||||
|
def __graceful_stop(self):
|
||||||
"""Handle the graceful stop of the thread."""
|
"""Handle the graceful stop of the thread."""
|
||||||
# Notify the user that the session has expired
|
# Notify the user that the session has expired
|
||||||
self.bot.send_message(self.chat.id, strings.conversation_expired)
|
self.bot.send_message(self.chat.id, strings.conversation_expired)
|
||||||
|
# Close the database session
|
||||||
# End the process
|
# End the process
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
Loading…
Reference in a new issue