Skip to content

Commit

Permalink
feat: make registration procedure a conversation
Browse files Browse the repository at this point in the history
fix: use ApplicationBuilder.post_init() to add_commands
refactor: rename login to register
  • Loading branch information
R1D3R175 committed Nov 13, 2023
1 parent 096ea3f commit 70f5ba5
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 95 deletions.
9 changes: 4 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
main module
"""
from module.commands import start, report, help, login
from module.commands import start, report, help, register_conv_handler
from module.data import HELP, REPORT

from telegram import BotCommand, Update
Expand All @@ -18,7 +18,7 @@ async def add_commands(app: Application) -> None:
BotCommand("start", "messaggio di benvenuto"),
BotCommand("help", "ricevi aiuto sui comandi"),
BotCommand("report", "segnala un problema"),
BotCommand("login", "procedura di autenticazione")
BotCommand("register", "procedura di registrazione")
]

await app.bot.set_my_commands(commands)
Expand All @@ -43,14 +43,13 @@ async def chatid(update: Update, context: ContextTypes.DEFAULT_TYPE):
MessageHandler(filters.Regex(HELP) & filters.ChatType.PRIVATE, help),
CommandHandler("report", report),
MessageHandler(filters.Regex(REPORT) & filters.ChatType.PRIVATE, report),
CommandHandler("login", login)
register_conv_handler()
]

app.add_handlers(handlers)

def main():
app = ApplicationBuilder().token("TOKEN").build()
add_commands(app)
app = ApplicationBuilder().token("TOKEN").post_init(add_commands).build()
add_handlers(app)

app.run_polling()
Expand Down
2 changes: 1 addition & 1 deletion module/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .start import start
from .help import help
from .report import report
from .login import login
from .register import register_conv_handler
88 changes: 0 additions & 88 deletions module/commands/login.py

This file was deleted.

174 changes: 174 additions & 0 deletions module/commands/register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
"""
/register command
"""
import re
import hashlib
from enum import Enum

from telegram import Update
from telegram.ext import ContextTypes, MessageHandler, CommandHandler, ConversationHandler, filters

from sqlalchemy import select
from data.db import Session
from data.db.models import User

class State(Enum):
"""
States of the register procedure
"""
EMAIL = 1
OTP = 2

async def register_entry(update: Update, context: ContextTypes.DEFAULT_TYPE) -> State:
"""
Called by the /register command.
Starts the registration procedure.
Args:
update: Update event
context: context passed by the handler
Returns:
State: the next state of the conversation
"""

await context.bot.send_message(
chat_id=update.effective_chat.id,
text="Invia la tua email studium"
)

return State.EMAIL

async def email_checker(update: Update, context: ContextTypes.DEFAULT_TYPE) -> State | int:
"""
Checks if the user isn't already registered.
Args:
update: Update event
context: context passed by the handler
Returns:
State: the next state of the conversation
int: constant ConversationHandler.END (if the user is already registered)
"""
email = update.message.text.strip()
email_digest = hashlib.sha256(email.encode()).hexdigest()

with Session() as session:
stmt = select(User).where((User.chat_id == update.effective_chat.id) | (User.email == email_digest))
result = session.scalars(stmt).first()

if result is not None:
await context.bot.send_message(
chat_id=update.effective_chat.id,
text="Sei gia' registrato!"
)

return ConversationHandler.END

context.user_data["email"] = email
context.user_data["otp"] = "123456"
context.user_data["tries"] = 0

await context.bot.send_message(
chat_id=update.effective_chat.id,
text="Invia l'OTP che ti e' stato inviato all'email da te indicata"
)

return State.OTP

async def otp_checker(update: Update, context: ContextTypes.DEFAULT_TYPE) -> State | int:
"""
Checks if the OTP sent to the email is valid.
Args:
update: Update event
context: context passed by the handler
Returns:
State: returns State.OTP if the OTP wasn't correct.
int: constant ConversationHandler.END (if the OTP was correct or too many wrong tries)
"""
if context.user_data["tries"] >= 3:
await context.bot.send_message(
chat_id=update.effective_chat.id,
text="Hai esaurito il numero di tentativi, riprova piu' tardi"
)

return ConversationHandler.END

otp = update.message.text.strip()
if otp != context.user_data["otp"]:
context.user_data["tries"] += 1

await context.bot.send_message(
chat_id=update.effective_chat.id,
text="OTP non corretto, controlla la tua mail"
)

return State.OTP

with Session() as session:
session.add(User=context.user_data["email"], chat_id=update.effective_chat.id)
session.commit()

await context.bot.send_message(
chat_id=update.effective_chat.id,
text="Registrazione completata!"
)

return ConversationHandler.END

def register_conv_handler() -> ConversationHandler:
"""
Creates the /register ConversationHandler.
States of the command:
- State.EMAIL: Waits for a text message containing the email (should match the regex)
- State.OTP: Waits for a text message containing the OTP sent to the email address.
Returns:
ConversationHandler: the created handler
"""
email_regex = re.compile(r"^[a-z]+\.[a-z]+@studium\.unict\.it$")
otp_regex = re.compile(r"^\d{6}$")

async def invalid_email(update: Update, context: ContextTypes.DEFAULT_TYPE) -> State:
await context.bot.send_message(
chat_id=update.effective_chat.id,
text="Email non valida, riprova"
)

return State.EMAIL

async def invalid_otp(update: Update, context: ContextTypes.DEFAULT_TYPE) -> State:
await context.bot.send_message(
chat_id=update.effective_chat.id,
text="OTP non valido, riprova"
)

return State.OTP

async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
context.bot.send_message(
chat_id=update.effective_chat.id,
text="Registrazione annullata!"
)

return ConversationHandler.END

return ConversationHandler(
entry_points=[CommandHandler("register", register_entry)],
states={
State.EMAIL: [
MessageHandler(filters.Regex(email_regex), email_checker),
MessageHandler(filters.TEXT & ~filters.Regex(email_regex), invalid_email)
],
State.OTP: [
MessageHandler(filters.Regex(otp_regex), otp_checker),
MessageHandler(filters.TEXT & ~filters.Regex(otp_regex), invalid_otp)
]
},
fallbacks=[CommandHandler("cancel", cancel)]
)
2 changes: 1 addition & 1 deletion module/data/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

HELP_CMD_TEXT = '\n'.join((
"📬 /report Fornisce la possibilità di poter inviare una segnalazione agli sviluppatori riguardante qualsiasi disservizio",
"🔑 /login Permette di effettuare il login al sistema"
"🔑 /register Permette di effettuare la registrazione al sistema"
))

REPORT = "Segnalazioni Rappresentanti 📬"
Expand Down

0 comments on commit 70f5ba5

Please sign in to comment.