mirror of
https://github.com/marcogll/talia_bot.git
synced 2026-01-13 21:35:19 +00:00
feat: Restructure admin menu and enhance Vikunja integration
Restructures the admin menu into a primary and secondary menu for better user experience. The primary menu now shows the most common actions. The secondary menu contains less frequent admin commands. Refactors the Vikunja module to be triggered by a menu button instead of a command. Adds "edit task" functionality to the Vikunja module. Fixes a bug where the button dispatcher was calling a non-existent function.
This commit is contained in:
37
app/main.py
37
app/main.py
@@ -15,8 +15,9 @@ from telegram.ext import (
|
|||||||
|
|
||||||
# Importamos las configuraciones y herramientas que creamos en otros archivos
|
# Importamos las configuraciones y herramientas que creamos en otros archivos
|
||||||
from config import TELEGRAM_BOT_TOKEN
|
from config import TELEGRAM_BOT_TOKEN
|
||||||
from permissions import get_user_role, is_admin
|
from permissions import get_user_role
|
||||||
from modules.onboarding import handle_start as onboarding_handle_start
|
from modules.onboarding import handle_start as onboarding_handle_start
|
||||||
|
from modules.onboarding import get_admin_secondary_menu
|
||||||
from modules.agenda import get_agenda
|
from modules.agenda import get_agenda
|
||||||
from modules.citas import request_appointment
|
from modules.citas import request_appointment
|
||||||
from modules.equipo import (
|
from modules.equipo import (
|
||||||
@@ -33,7 +34,8 @@ from modules.servicios import get_service_info
|
|||||||
from modules.admin import get_system_status
|
from modules.admin import get_system_status
|
||||||
from modules.print import print_handler
|
from modules.print import print_handler
|
||||||
from modules.create_tag import create_tag_conv_handler, create_tag_start
|
from modules.create_tag import create_tag_conv_handler, create_tag_start
|
||||||
from modules.vikunja import vikunja_conv_handler
|
from modules.vikunja import vikunja_conv_handler, get_tasks as get_vikunja_tasks
|
||||||
|
|
||||||
from scheduler import schedule_daily_summary
|
from scheduler import schedule_daily_summary
|
||||||
|
|
||||||
# Configuramos el sistema de logs para ver mensajes de estado en la consola
|
# Configuramos el sistema de logs para ver mensajes de estado en la consola
|
||||||
@@ -64,17 +66,14 @@ async def button_dispatcher(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
|||||||
Dependiendo de qué botón se presione, ejecuta una acción diferente.
|
Dependiendo de qué botón se presione, ejecuta una acción diferente.
|
||||||
"""
|
"""
|
||||||
query = update.callback_query
|
query = update.callback_query
|
||||||
await query.answer() # Avisa a Telegram que recibimos el clic
|
await query.answer()
|
||||||
logger.info(f"El despachador recibió una consulta: {query.data}")
|
logger.info(f"El despachador recibió una consulta: {query.data}")
|
||||||
|
|
||||||
# Texto por defecto si no encontramos la acción
|
|
||||||
response_text = "Acción no reconocida."
|
response_text = "Acción no reconocida."
|
||||||
reply_markup = None
|
reply_markup = None
|
||||||
|
|
||||||
# Diccionario de acciones simples (que solo devuelven texto)
|
|
||||||
simple_handlers = {
|
simple_handlers = {
|
||||||
'view_agenda': get_agenda,
|
'view_agenda': get_agenda,
|
||||||
'view_tasks': get_tasks,
|
|
||||||
'view_requests_status': view_requests_status,
|
'view_requests_status': view_requests_status,
|
||||||
'schedule_appointment': request_appointment,
|
'schedule_appointment': request_appointment,
|
||||||
'get_service_info': get_service_info,
|
'get_service_info': get_service_info,
|
||||||
@@ -82,43 +81,38 @@ async def button_dispatcher(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
|||||||
'manage_users': lambda: "Función de gestión de usuarios no implementada.",
|
'manage_users': lambda: "Función de gestión de usuarios no implementada.",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Diccionario de acciones complejas (que devuelven texto y botones)
|
|
||||||
complex_handlers = {
|
complex_handlers = {
|
||||||
'view_pending': view_pending,
|
'view_pending': view_pending,
|
||||||
|
'admin_menu': get_admin_secondary_menu,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Buscamos qué función ejecutar según el dato del botón (query.data)
|
|
||||||
if query.data in simple_handlers:
|
if query.data in simple_handlers:
|
||||||
response_text = simple_handlers[query.data]()
|
response_text = simple_handlers[query.data]()
|
||||||
|
await query.edit_message_text(text=response_text, parse_mode='Markdown')
|
||||||
elif query.data in complex_handlers:
|
elif query.data in complex_handlers:
|
||||||
response_text, reply_markup = complex_handlers[query.data]()
|
response_text, reply_markup = complex_handlers[query.data]()
|
||||||
|
await query.edit_message_text(text=response_text, reply_markup=reply_markup, parse_mode='Markdown')
|
||||||
elif query.data.startswith(('approve:', 'reject:')):
|
elif query.data.startswith(('approve:', 'reject:')):
|
||||||
# Manejo especial para botones de aprobar o rechazar
|
|
||||||
response_text = handle_approval_action(query.data)
|
response_text = handle_approval_action(query.data)
|
||||||
|
await query.edit_message_text(text=response_text, parse_mode='Markdown')
|
||||||
elif query.data == 'start_create_tag':
|
elif query.data == 'start_create_tag':
|
||||||
# Iniciamos el flujo de creación de tag
|
|
||||||
await query.message.reply_text("Iniciando creación de tag...")
|
await query.message.reply_text("Iniciando creación de tag...")
|
||||||
# Aquí simulamos el comando /create_tag
|
|
||||||
return await create_tag_start(update, context)
|
return await create_tag_start(update, context)
|
||||||
|
else:
|
||||||
|
# Si no es ninguna de las acciones conocidas, asumimos que es para un ConversationHandler
|
||||||
|
# y no hacemos nada aquí para no interferir.
|
||||||
|
logger.warning(f"Consulta no manejada por el despachador principal: {query.data}")
|
||||||
|
|
||||||
# Editamos el mensaje original con la nueva información
|
|
||||||
await query.edit_message_text(text=response_text, reply_markup=reply_markup, parse_mode='Markdown')
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
"""Función principal que arranca el bot."""
|
"""Función principal que arranca el bot."""
|
||||||
# Verificamos que tengamos el token del bot
|
|
||||||
if not TELEGRAM_BOT_TOKEN:
|
if not TELEGRAM_BOT_TOKEN:
|
||||||
logger.error("TELEGRAM_BOT_TOKEN no está configurado en las variables de entorno.")
|
logger.error("TELEGRAM_BOT_TOKEN no está configurado en las variables de entorno.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Creamos la aplicación del bot
|
|
||||||
application = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
|
application = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
|
||||||
|
|
||||||
# Programamos el resumen diario
|
|
||||||
schedule_daily_summary(application)
|
schedule_daily_summary(application)
|
||||||
|
|
||||||
# Configuramos un "manejador de conversación" para proponer actividades
|
|
||||||
# Esto permite que el bot haga varias preguntas seguidas (descripción, duración)
|
|
||||||
conv_handler = ConversationHandler(
|
conv_handler = ConversationHandler(
|
||||||
entry_points=[CallbackQueryHandler(propose_activity_start, pattern='^propose_activity$')],
|
entry_points=[CallbackQueryHandler(propose_activity_start, pattern='^propose_activity$')],
|
||||||
states={
|
states={
|
||||||
@@ -129,7 +123,8 @@ def main() -> None:
|
|||||||
per_message=False
|
per_message=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Registramos todos los manejadores de eventos en la aplicación
|
# El order de los handlers importa. El dispatcher debe ir después de los ConversationHandlers
|
||||||
|
# para no interceptar sus callbacks.
|
||||||
application.add_handler(conv_handler)
|
application.add_handler(conv_handler)
|
||||||
application.add_handler(create_tag_conv_handler())
|
application.add_handler(create_tag_conv_handler())
|
||||||
application.add_handler(vikunja_conv_handler())
|
application.add_handler(vikunja_conv_handler())
|
||||||
@@ -137,10 +132,8 @@ def main() -> None:
|
|||||||
application.add_handler(CommandHandler("print", print_handler))
|
application.add_handler(CommandHandler("print", print_handler))
|
||||||
application.add_handler(CallbackQueryHandler(button_dispatcher))
|
application.add_handler(CallbackQueryHandler(button_dispatcher))
|
||||||
|
|
||||||
# Iniciamos el bot (se queda escuchando mensajes)
|
|
||||||
logger.info("Iniciando Talía Bot...")
|
logger.info("Iniciando Talía Bot...")
|
||||||
application.run_polling()
|
application.run_polling()
|
||||||
|
|
||||||
# Si este archivo se ejecuta directamente, llamamos a la función main()
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -13,14 +13,26 @@ def get_owner_menu():
|
|||||||
return InlineKeyboardMarkup(keyboard)
|
return InlineKeyboardMarkup(keyboard)
|
||||||
|
|
||||||
def get_admin_menu():
|
def get_admin_menu():
|
||||||
"""Crea el menú de botones para los Administradores."""
|
"""Crea el menú de botones principal para los Administradores."""
|
||||||
keyboard = [
|
keyboard = [
|
||||||
[InlineKeyboardButton("📋 Ver Tareas (Vikunja)", callback_data='view_tasks')],
|
[InlineKeyboardButton("⏳ Revisar Pendientes", callback_data='view_pending')],
|
||||||
[InlineKeyboardButton("🏷️ Crear Tag NFC", callback_data='start_create_tag')],
|
[InlineKeyboardButton("📅 Agenda", callback_data='view_agenda')],
|
||||||
[InlineKeyboardButton("📊 Estado del sistema", callback_data='view_system_status')],
|
[InlineKeyboardButton("🏷️ Crear Tag", callback_data='start_create_tag')],
|
||||||
|
[InlineKeyboardButton("▶️ Más opciones", callback_data='admin_menu')],
|
||||||
]
|
]
|
||||||
return InlineKeyboardMarkup(keyboard)
|
return InlineKeyboardMarkup(keyboard)
|
||||||
|
|
||||||
|
def get_admin_secondary_menu():
|
||||||
|
"""Crea el menú secundario para Administradores."""
|
||||||
|
text = "Aquí tienes más opciones de administración:"
|
||||||
|
keyboard = [
|
||||||
|
[InlineKeyboardButton("📋 Gestionar Tareas (Vikunja)", callback_data='manage_vikunja')],
|
||||||
|
[InlineKeyboardButton("📊 Estado del sistema", callback_data='view_system_status')],
|
||||||
|
[InlineKeyboardButton("👥 Gestionar Usuarios", callback_data='manage_users')],
|
||||||
|
]
|
||||||
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
|
return text, reply_markup
|
||||||
|
|
||||||
def get_team_menu():
|
def get_team_menu():
|
||||||
"""Crea el menú de botones para los Miembros del Equipo."""
|
"""Crea el menú de botones para los Miembros del Equipo."""
|
||||||
keyboard = [
|
keyboard = [
|
||||||
@@ -43,14 +55,13 @@ def handle_start(user_role):
|
|||||||
"""
|
"""
|
||||||
welcome_message = "Hola, soy Talía. ¿En qué puedo ayudarte hoy?"
|
welcome_message = "Hola, soy Talía. ¿En qué puedo ayudarte hoy?"
|
||||||
|
|
||||||
# Dependiendo del rol, llamamos a una función de menú diferente
|
|
||||||
if user_role == "owner":
|
if user_role == "owner":
|
||||||
menu = get_owner_menu()
|
menu = get_owner_menu()
|
||||||
elif user_role == "admin":
|
elif user_role == "admin":
|
||||||
menu = get_admin_menu()
|
menu = get_admin_menu()
|
||||||
elif user_role == "team":
|
elif user_role == "team":
|
||||||
menu = get_team_menu()
|
menu = get_team_menu()
|
||||||
else: # Por defecto, si no es ninguno de los anteriores, es un cliente
|
else:
|
||||||
menu = get_client_menu()
|
menu = get_client_menu()
|
||||||
|
|
||||||
return welcome_message, menu
|
return welcome_message, menu
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ from app.permissions import is_admin
|
|||||||
# Configuración del logger
|
# Configuración del logger
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Definición de los estados de la conversación
|
# Definición de los estados de la conversación para añadir y editar tareas
|
||||||
SELECTING_ACTION, ADDING_TASK = range(2)
|
SELECTING_ACTION, ADDING_TASK, SELECTING_TASK_TO_EDIT, EDITING_TASK = range(4)
|
||||||
|
|
||||||
def get_vikunja_headers():
|
def get_vikunja_headers():
|
||||||
"""Devuelve los headers necesarios para la API de Vikunja."""
|
"""Devuelve los headers necesarios para la API de Vikunja."""
|
||||||
@@ -29,29 +29,13 @@ def get_vikunja_headers():
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
async def vik_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
def get_tasks():
|
||||||
"""Inicia la conversación de Vikunja y muestra el menú de acciones."""
|
"""
|
||||||
if not is_admin(update.effective_chat.id):
|
Obtiene y formatea la lista de tareas de Vikunja.
|
||||||
await update.message.reply_text("No tienes permiso para usar este comando.")
|
Esta función es síncrona y devuelve un string.
|
||||||
return ConversationHandler.END
|
"""
|
||||||
|
|
||||||
keyboard = [
|
|
||||||
[InlineKeyboardButton("Ver Tareas", callback_data='view_tasks')],
|
|
||||||
[InlineKeyboardButton("Añadir Tarea", callback_data='add_task')],
|
|
||||||
[InlineKeyboardButton("Cancelar", callback_data='cancel')],
|
|
||||||
]
|
|
||||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
|
||||||
await update.message.reply_text("Selecciona una opción para Vikunja:", reply_markup=reply_markup)
|
|
||||||
return SELECTING_ACTION
|
|
||||||
|
|
||||||
async def view_tasks(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
|
||||||
"""Muestra la lista de tareas de Vikunja."""
|
|
||||||
query = update.callback_query
|
|
||||||
await query.answer()
|
|
||||||
|
|
||||||
if not VIKUNJA_API_TOKEN:
|
if not VIKUNJA_API_TOKEN:
|
||||||
await query.edit_message_text("Error: VIKUNJA_API_TOKEN no configurado.")
|
return "Error: VIKUNJA_API_TOKEN no configurado."
|
||||||
return ConversationHandler.END
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get(f"{VIKUNJA_API_URL}/projects/1/tasks", headers=get_vikunja_headers())
|
response = requests.get(f"{VIKUNJA_API_URL}/projects/1/tasks", headers=get_vikunja_headers())
|
||||||
@@ -59,19 +43,32 @@ async def view_tasks(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
|||||||
tasks = response.json()
|
tasks = response.json()
|
||||||
|
|
||||||
if not tasks:
|
if not tasks:
|
||||||
text = "No tienes tareas pendientes en Vikunja."
|
return "No tienes tareas pendientes en Vikunja."
|
||||||
else:
|
|
||||||
text = "📋 *Tus Tareas en Vikunja*\n\n"
|
|
||||||
for task in tasks[:10]:
|
|
||||||
status = "✅" if task.get('done') else "⏳"
|
|
||||||
text += f"{status} *{task.get('title')}*\n"
|
|
||||||
|
|
||||||
await query.edit_message_text(text, parse_mode='Markdown')
|
text = "📋 *Tus Tareas en Vikunja*\n\n"
|
||||||
|
for task in sorted(tasks, key=lambda t: t.get('id', 0))[:10]:
|
||||||
|
status = "✅" if task.get('done') else "⏳"
|
||||||
|
text += f"{status} `{task.get('id')}`: *{task.get('title')}*\n"
|
||||||
|
return text
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error al obtener tareas de Vikunja: {e}")
|
logger.error(f"Error al obtener tareas de Vikunja: {e}")
|
||||||
await query.edit_message_text(f"Error al conectar con Vikunja: {e}")
|
return f"Error al conectar con Vikunja: {e}"
|
||||||
|
|
||||||
return ConversationHandler.END
|
async def vikunja_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
|
"""Muestra el menú principal de acciones de Vikunja."""
|
||||||
|
query = update.callback_query
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
keyboard = [
|
||||||
|
[InlineKeyboardButton("Añadir Tarea", callback_data='add_task')],
|
||||||
|
[InlineKeyboardButton("Editar Tarea", callback_data='edit_task_start')],
|
||||||
|
[InlineKeyboardButton("Volver", callback_data='cancel')],
|
||||||
|
]
|
||||||
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
|
|
||||||
|
tasks_list = get_tasks()
|
||||||
|
await query.edit_message_text(text=f"{tasks_list}\n\nSelecciona una acción:", reply_markup=reply_markup, parse_mode='Markdown')
|
||||||
|
return SELECTING_ACTION
|
||||||
|
|
||||||
async def request_task_title(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def request_task_title(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Solicita al usuario el título de la nueva tarea."""
|
"""Solicita al usuario el título de la nueva tarea."""
|
||||||
@@ -83,13 +80,7 @@ async def request_task_title(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
|||||||
async def add_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def add_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Añade una nueva tarea a Vikunja."""
|
"""Añade una nueva tarea a Vikunja."""
|
||||||
task_title = update.message.text
|
task_title = update.message.text
|
||||||
|
|
||||||
if not VIKUNJA_API_TOKEN:
|
|
||||||
await update.message.reply_text("Error: VIKUNJA_API_TOKEN no configurado.")
|
|
||||||
return ConversationHandler.END
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Usamos un project_id=1 hardcodeado como se definió en el plan
|
|
||||||
data = {"title": task_title, "project_id": 1}
|
data = {"title": task_title, "project_id": 1}
|
||||||
response = requests.post(f"{VIKUNJA_API_URL}/tasks", headers=get_vikunja_headers(), json=data)
|
response = requests.post(f"{VIKUNJA_API_URL}/tasks", headers=get_vikunja_headers(), json=data)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
@@ -100,8 +91,71 @@ async def add_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
|||||||
|
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
|
|
||||||
|
async def select_task_to_edit(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
|
"""Muestra los botones para seleccionar qué tarea editar."""
|
||||||
|
query = update.callback_query
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{VIKUNJA_API_URL}/projects/1/tasks", headers=get_vikunja_headers())
|
||||||
|
response.raise_for_status()
|
||||||
|
tasks = [task for task in response.json() if not task.get('done')]
|
||||||
|
|
||||||
|
if not tasks:
|
||||||
|
await query.edit_message_text("No hay tareas pendientes para editar.")
|
||||||
|
return ConversationHandler.END
|
||||||
|
|
||||||
|
keyboard = []
|
||||||
|
for task in sorted(tasks, key=lambda t: t.get('id', 0))[:10]:
|
||||||
|
keyboard.append([InlineKeyboardButton(
|
||||||
|
f"{task.get('id')}: {task.get('title')}",
|
||||||
|
callback_data=f"edit_task:{task.get('id')}"
|
||||||
|
)])
|
||||||
|
keyboard.append([InlineKeyboardButton("Cancelar", callback_data='cancel')])
|
||||||
|
|
||||||
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
|
await query.edit_message_text("Selecciona la tarea que quieres editar:", reply_markup=reply_markup)
|
||||||
|
return SELECTING_TASK_TO_EDIT
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al obtener tareas para editar: {e}")
|
||||||
|
await query.edit_message_text("Error al obtener la lista de tareas.")
|
||||||
|
return ConversationHandler.END
|
||||||
|
|
||||||
|
async def request_new_task_title(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
|
"""Solicita el nuevo título para la tarea seleccionada."""
|
||||||
|
query = update.callback_query
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
task_id = query.data.split(':')[1]
|
||||||
|
context.user_data['task_id_to_edit'] = task_id
|
||||||
|
|
||||||
|
await query.edit_message_text(f"Introduce el nuevo título para la tarea `{task_id}`:", parse_mode='Markdown')
|
||||||
|
return EDITING_TASK
|
||||||
|
|
||||||
|
async def edit_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
|
"""Actualiza el título de una tarea en Vikunja."""
|
||||||
|
new_title = update.message.text
|
||||||
|
task_id = context.user_data.get('task_id_to_edit')
|
||||||
|
|
||||||
|
if not task_id:
|
||||||
|
await update.message.reply_text("Error: No se encontró el ID de la tarea a editar.")
|
||||||
|
return ConversationHandler.END
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = {"title": new_title}
|
||||||
|
response = requests.put(f"{VIKUNJA_API_URL}/tasks/{task_id}", headers=get_vikunja_headers(), json=data)
|
||||||
|
response.raise_for_status()
|
||||||
|
await update.message.reply_text(f"✅ Tarea `{task_id}` actualizada a *{new_title}*", parse_mode='Markdown')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al editar la tarea {task_id}: {e}")
|
||||||
|
await update.message.reply_text("Error al actualizar la tarea.")
|
||||||
|
finally:
|
||||||
|
del context.user_data['task_id_to_edit']
|
||||||
|
|
||||||
|
return ConversationHandler.END
|
||||||
|
|
||||||
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
"""Cancela la conversación."""
|
"""Cancela la conversación actual."""
|
||||||
query = update.callback_query
|
query = update.callback_query
|
||||||
await query.answer()
|
await query.answer()
|
||||||
await query.edit_message_text("Operación cancelada.")
|
await query.edit_message_text("Operación cancelada.")
|
||||||
@@ -110,16 +164,19 @@ async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
|||||||
def vikunja_conv_handler():
|
def vikunja_conv_handler():
|
||||||
"""Crea el ConversationHandler para el flujo de Vikunja."""
|
"""Crea el ConversationHandler para el flujo de Vikunja."""
|
||||||
return ConversationHandler(
|
return ConversationHandler(
|
||||||
entry_points=[CommandHandler('vik', vik_start)],
|
entry_points=[CallbackQueryHandler(vikunja_menu, pattern='^manage_vikunja$')],
|
||||||
states={
|
states={
|
||||||
SELECTING_ACTION: [
|
SELECTING_ACTION: [
|
||||||
CallbackQueryHandler(view_tasks, pattern='^view_tasks$'),
|
|
||||||
CallbackQueryHandler(request_task_title, pattern='^add_task$'),
|
CallbackQueryHandler(request_task_title, pattern='^add_task$'),
|
||||||
|
CallbackQueryHandler(select_task_to_edit, pattern='^edit_task_start$'),
|
||||||
CallbackQueryHandler(cancel, pattern='^cancel$'),
|
CallbackQueryHandler(cancel, pattern='^cancel$'),
|
||||||
],
|
],
|
||||||
ADDING_TASK: [
|
ADDING_TASK: [MessageHandler(filters.TEXT & ~filters.COMMAND, add_task)],
|
||||||
MessageHandler(filters.TEXT & ~filters.COMMAND, add_task)
|
SELECTING_TASK_TO_EDIT: [
|
||||||
|
CallbackQueryHandler(request_new_task_title, pattern=r'^edit_task:\d+$'),
|
||||||
|
CallbackQueryHandler(cancel, pattern='^cancel$'),
|
||||||
],
|
],
|
||||||
|
EDITING_TASK: [MessageHandler(filters.TEXT & ~filters.COMMAND, edit_task)],
|
||||||
},
|
},
|
||||||
fallbacks=[CommandHandler('cancel', cancel)],
|
fallbacks=[CommandHandler('cancel', cancel)],
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user