mirror of
https://github.com/marcogll/talia_bot.git
synced 2026-01-13 13:25:19 +00:00
docs: Add comments and document /create_tag command
This commit adds detailed inline comments to the `app/modules/create_tag.py` module to improve code clarity and maintainability. It also updates the `README.md` file to include a new section documenting the functionality and usage of the `/create_tag` command.
This commit is contained in:
15
README.md
15
README.md
@@ -132,6 +132,21 @@ Cada módulo cumple una responsabilidad única:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ⚡ Comandos Adicionales
|
||||||
|
|
||||||
|
### `/create_tag`
|
||||||
|
|
||||||
|
Este comando inicia un flujo conversacional para generar un tag de identificación en formato Base64, compatible con aplicaciones de escritura NFC. El bot solicitará los siguientes datos:
|
||||||
|
|
||||||
|
* **Nombre**
|
||||||
|
* **Número de empleado**
|
||||||
|
* **Sucursal**
|
||||||
|
* **ID de Telegram**
|
||||||
|
|
||||||
|
Al finalizar, el bot devolverá una cadena de texto en Base64 que contiene un objeto JSON con la información proporcionada.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 🔁 Flujo General de Ejecución
|
## 🔁 Flujo General de Ejecución
|
||||||
|
|
||||||
1. Usuario envía mensaje o interactúa con botones
|
1. Usuario envía mensaje o interactúa con botones
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
# app/modules/create_tag.py
|
# app/modules/create_tag.py
|
||||||
|
"""
|
||||||
|
This module contains the functionality for the /create_tag command.
|
||||||
|
|
||||||
|
It uses a ConversationHandler to guide the user through a series of questions
|
||||||
|
to collect data (name, employee number, branch, and Telegram ID), and then
|
||||||
|
generates a Base64-encoded JSON string from that data. This string is intended
|
||||||
|
to be used for creating an NFC tag.
|
||||||
|
"""
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@@ -11,40 +19,62 @@ from telegram.ext import (
|
|||||||
filters,
|
filters,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable logging
|
# Enable logging to monitor the bot's operation and for debugging.
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Define states for the conversation
|
# Define the states for the conversation. These states are used to track the
|
||||||
|
# user's progress through the conversation and determine which handler function
|
||||||
|
# should be executed next.
|
||||||
NAME, NUM_EMP, SUCURSAL, TELEGRAM_ID = range(4)
|
NAME, NUM_EMP, SUCURSAL, TELEGRAM_ID = range(4)
|
||||||
|
|
||||||
async def create_tag_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def create_tag_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Starts the conversation to create a new tag."""
|
"""
|
||||||
|
Starts the conversation to create a new tag when the /create_tag command
|
||||||
|
is issued. It prompts the user for the first piece of information (name).
|
||||||
|
"""
|
||||||
await update.message.reply_text("Vamos a crear un nuevo tag. Por favor, dime el nombre:")
|
await update.message.reply_text("Vamos a crear un nuevo tag. Por favor, dime el nombre:")
|
||||||
|
# The function returns the next state, which is NAME, so the conversation
|
||||||
|
# knows which handler to call next.
|
||||||
return NAME
|
return NAME
|
||||||
|
|
||||||
async def get_name(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def get_name(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Stores the name and asks for the employee number."""
|
"""
|
||||||
|
Stores the user's provided name in the context and then asks for the
|
||||||
|
next piece of information, the employee number.
|
||||||
|
"""
|
||||||
context.user_data['name'] = update.message.text
|
context.user_data['name'] = update.message.text
|
||||||
await update.message.reply_text("Gracias. Ahora, por favor, dime el número de empleado:")
|
await update.message.reply_text("Gracias. Ahora, por favor, dime el número de empleado:")
|
||||||
|
# The function returns the next state, NUM_EMP.
|
||||||
return NUM_EMP
|
return NUM_EMP
|
||||||
|
|
||||||
async def get_num_emp(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def get_num_emp(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Stores the employee number and asks for the branch."""
|
"""
|
||||||
|
Stores the employee number and proceeds to ask for the branch name.
|
||||||
|
"""
|
||||||
context.user_data['num_emp'] = update.message.text
|
context.user_data['num_emp'] = update.message.text
|
||||||
await update.message.reply_text("Entendido. Ahora, por favor, dime la sucursal:")
|
await update.message.reply_text("Entendido. Ahora, por favor, dime la sucursal:")
|
||||||
|
# The function returns the next state, SUCURSAL.
|
||||||
return SUCURSAL
|
return SUCURSAL
|
||||||
|
|
||||||
async def get_sucursal(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def get_sucursal(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Stores the branch and asks for the Telegram ID."""
|
"""
|
||||||
|
Stores the branch name and asks for the final piece of information,
|
||||||
|
the user's Telegram ID.
|
||||||
|
"""
|
||||||
context.user_data['sucursal'] = update.message.text
|
context.user_data['sucursal'] = update.message.text
|
||||||
await update.message.reply_text("Perfecto. Finalmente, por favor, dime el ID de Telegram:")
|
await update.message.reply_text("Perfecto. Finalmente, por favor, dime el ID de Telegram:")
|
||||||
|
# The function returns the next state, TELEGRAM_ID.
|
||||||
return TELEGRAM_ID
|
return TELEGRAM_ID
|
||||||
|
|
||||||
async def get_telegram_id(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def get_telegram_id(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Stores the Telegram ID, generates the Base64 string, and ends the conversation."""
|
"""
|
||||||
|
Stores the Telegram ID, assembles all the collected data into a JSON
|
||||||
|
object, encodes it into a Base64 string, and sends the result back to
|
||||||
|
the user. This function concludes the conversation.
|
||||||
|
"""
|
||||||
context.user_data['telegram_id'] = update.message.text
|
context.user_data['telegram_id'] = update.message.text
|
||||||
|
|
||||||
# Create the JSON object from the collected data
|
# Create a dictionary from the data collected and stored in user_data.
|
||||||
tag_data = {
|
tag_data = {
|
||||||
"name": context.user_data.get('name'),
|
"name": context.user_data.get('name'),
|
||||||
"num_emp": context.user_data.get('num_emp'),
|
"num_emp": context.user_data.get('num_emp'),
|
||||||
@@ -52,36 +82,61 @@ async def get_telegram_id(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
|
|||||||
"telegram_id": context.user_data.get('telegram_id'),
|
"telegram_id": context.user_data.get('telegram_id'),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert the dictionary to a JSON string
|
# Convert the Python dictionary into a JSON formatted string.
|
||||||
json_string = json.dumps(tag_data)
|
json_string = json.dumps(tag_data)
|
||||||
|
|
||||||
# Encode the JSON string to Base64
|
# Encode the JSON string into Base64. The string is first encoded to
|
||||||
|
# UTF-8 bytes, which is then encoded to Base64 bytes, and finally
|
||||||
|
# decoded back to a UTF-8 string for display.
|
||||||
base64_bytes = base64.b64encode(json_string.encode('utf-8'))
|
base64_bytes = base64.b64encode(json_string.encode('utf-8'))
|
||||||
base64_string = base64_bytes.decode('utf-8')
|
base64_string = base64_bytes.decode('utf-8')
|
||||||
|
|
||||||
await update.message.reply_text(f"¡Gracias! Aquí está tu tag en formato Base64:\n\n`{base64_string}`", parse_mode='Markdown')
|
await update.message.reply_text(f"¡Gracias! Aquí está tu tag en formato Base64:\n\n`{base64_string}`", parse_mode='Markdown')
|
||||||
|
|
||||||
# Clean up user_data
|
# Clean up the user_data dictionary to ensure no data from this
|
||||||
|
# conversation is accidentally used in another one.
|
||||||
context.user_data.clear()
|
context.user_data.clear()
|
||||||
|
|
||||||
|
# End the conversation.
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
|
|
||||||
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Cancels and ends the conversation."""
|
"""
|
||||||
|
Cancels and ends the conversation if the user issues the /cancel command.
|
||||||
|
It also clears any data that has been collected so far.
|
||||||
|
"""
|
||||||
await update.message.reply_text("Creación de tag cancelada.")
|
await update.message.reply_text("Creación de tag cancelada.")
|
||||||
context.user_data.clear()
|
context.user_data.clear()
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
|
|
||||||
def create_tag_conv_handler():
|
def create_tag_conv_handler():
|
||||||
"""Creates a conversation handler for the /create_tag command."""
|
"""
|
||||||
|
Creates and returns a ConversationHandler for the /create_tag command.
|
||||||
|
This handler manages the entire conversational flow, from starting the
|
||||||
|
conversation to handling user inputs and ending the conversation.
|
||||||
|
"""
|
||||||
return ConversationHandler(
|
return ConversationHandler(
|
||||||
|
# The entry_points list defines how the conversation can be started.
|
||||||
|
# In this case, it's started by the /create_tag command.
|
||||||
entry_points=[CommandHandler('create_tag', create_tag_start)],
|
entry_points=[CommandHandler('create_tag', create_tag_start)],
|
||||||
|
|
||||||
|
# The states dictionary maps the conversation states to their
|
||||||
|
# respective handler functions. When the conversation is in a
|
||||||
|
# particular state, the corresponding handler is called to process
|
||||||
|
# the user's message.
|
||||||
states={
|
states={
|
||||||
NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_name)],
|
NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_name)],
|
||||||
NUM_EMP: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_num_emp)],
|
NUM_EMP: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_num_emp)],
|
||||||
SUCURSAL: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_sucursal)],
|
SUCURSAL: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_sucursal)],
|
||||||
TELEGRAM_ID: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_telegram_id)],
|
TELEGRAM_ID: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_telegram_id)],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
# The fallbacks list defines handlers that are called if the user
|
||||||
|
# sends a message that doesn't match the current state's handler.
|
||||||
|
# Here, it's used to handle the /cancel command.
|
||||||
fallbacks=[CommandHandler('cancel', cancel)],
|
fallbacks=[CommandHandler('cancel', cancel)],
|
||||||
|
|
||||||
|
# per_message=False means the conversation is tied to the user, not
|
||||||
|
# to a specific message, which is standard for this type of flow.
|
||||||
per_message=False
|
per_message=False
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user