\n\n\n\n Mi viaje con la API de Telegram Bot: Más allá de las notificaciones simples - AI7Bot \n

Mi viaje con la API de Telegram Bot: Más allá de las notificaciones simples

📖 13 min read2,553 wordsUpdated Mar 25, 2026

Hola a todos, Marcus aquí de ai7bot.com. Es 20 de marzo de 2026, y he estado pensando mucho últimamente en algo que se ha convertido en un poco de un caballo de batalla silencioso en el mundo de los bots: la API de Telegram Bot. No es la más nueva en el mercado, no es tan llamativa como algunos de los marcos de IA que están en los titulares, pero, vaya, es poderosa y, más importante, increíblemente accesible. Hoy, quiero hablar sobre cómo la API de Telegram Bot ya no es solo para notificaciones simples. Vamos a explorar cómo puedes usarla para construir herramientas sorprendentemente sofisticadas e interactivas – específicamente, una experiencia de usuario de múltiples pasos para la recopilación de datos o la ejecución de comandos complejos. Olvídate de esos ejemplos de “enviar un mensaje”; vamos por algo más sustancial.

Recuerdo mi primera incursión en los bots de Telegram en 2018. Construí un bot súper básico que solo respondía lo que le enviabas. Revolucionario, lo sé. Pero incluso entonces, la simplicidad de empezar con la API era sorprendente. Avanzamos hasta hoy, y la he utilizado para todo, desde herramientas internas del equipo que rastrean las actualizaciones de proyectos hasta un bot que me ayuda a gestionar mi creciente lista de artículos por escribir. Lo que a menudo se pasa por alto es lo bien que Telegram ha desarrollado su API para manejar interacciones complejas sin hacerte perder la paciencia. Hablamos de gestión de estado, teclados en línea y teclados personalizados: todos los ingredientes para una experiencia de bot realmente atractiva.

Más Allá de los Comandos Simples: Construyendo un Flujo de Trabajo de Múltiples Pasos

El mayor obstáculo que enfrentan las personas al pasar de los simples “comandos de barra” es gestionar el contexto. Si tu bot hace una pregunta, ¿cómo sabe que el siguiente mensaje del usuario es la respuesta a esa pregunta específica y no un nuevo comando o un pensamiento aleatorio? Aquí es donde entra la gestión del estado. No estamos hablando de una base de datos completa aquí, aunque ciertamente podrías integrar una. Para muchas aplicaciones, un simple diccionario en memoria o un almacenamiento ligero de clave-valor es más que suficiente.

Imaginemos que queremos construir un bot que ayude a un usuario a registrar una nueva “tarea” o “idea.” Necesita preguntar por un título, luego una descripción y, quizás, un nivel de prioridad. Tres pasos distintos, tres piezas de información que necesitamos recopilar en orden. Si solo tenemos un montón de comandos /start y /log, rápidamente se vuelve ineficaz.

La Idea Principal: Estado del Usuario y Flujo de Conversación

Mi enfoque generalmente implica mantener un diccionario donde la clave es el ID del usuario y el valor es un objeto que representa su estado de conversación actual. Este objeto de estado podría contener:

  • current_step: Un enum o cadena que indica en qué parte del flujo de trabajo se encuentran (por ejemplo, ‘AWAITING_TITLE’, ‘AWAITING_DESCRIPTION’).
  • temp_data: Un diccionario para almacenar las piezas de información recopiladas hasta ahora para el flujo de trabajo actual (por ejemplo, {'title': 'Mi Nueva Idea', 'description': ''}).

Cuando llega un mensaje, el bot verifica el estado del usuario. Si están en un paso específico del flujo de trabajo, procesa su mensaje como entrada para ese paso. Si no, lo trata como un comando general.

Ejemplo Práctico: Un Bot Simple para Registrar Tareas

Pongámonos manos a la obra. Vamos a construir un bot para registrar tareas muy simplificado. El usuario iniciará un comando de “nueva tarea”, el bot pedirá un título, luego una descripción y finalmente confirmará. Para simplificar, almacenaremos el estado en un diccionario de Python. Para producción, probablemente querrías algo más persistente como Redis o una pequeña base de datos SQLite.

Configurando Tu Bot y Obteniendo el Token de la API

Primero lo primero, necesitas un bot. Ve a BotFather en Telegram (busca @BotFather), envíale /newbot, sigue las instrucciones y te dará un token de API. ¡Mantén ese token en secreto!

Usaremos la biblioteca python-telegram-bot, que simplifica significativamente la interacción con la API de Telegram Bot. Instálala con pip install python-telegram-bot.

La Estructura del Código: Gestión del Estado y Controladores

A continuación, se muestra un esqueleto básico para nuestro bot. Observa cómo utilizaremos un diccionario global user_states para hacer seguimiento de en qué parte de su conversación se encuentra cada usuario. En un escenario del mundo real, querrías persistir esto a través de reinicios del bot.


from telegram import Update, ForceReply
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes

# Reemplaza con tu token de bot real
BOT_TOKEN = "YOUR_BOT_TOKEN_HERE"

# --- Gestión del Estado del Usuario ---
# En una aplicación real, esto sería persistente (por ejemplo, Redis, base de datos)
user_states = {}

# Define los estados para nuestro flujo de trabajo
STATE_NONE = 0
STATE_AWAITING_TITLE = 1
STATE_AWAITING_DESCRIPTION = 2

# --- Comandos del Bot ---

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Envía un mensaje de bienvenida cuando se emite el comando /start."""
 user_id = update.effective_user.id
 user_states[user_id] = {'current_step': STATE_NONE, 'task_data': {}}
 await update.message.reply_text('¡Hola! Soy tu bot registrador de tareas. Usa /new_task para empezar a registrar una tarea.')

async def new_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Inicia el flujo de trabajo de nueva tarea."""
 user_id = update.effective_user.id
 user_states[user_id] = {'current_step': STATE_AWAITING_TITLE, 'task_data': {}}
 await update.message.reply_text('Está bien, vamos a crear una nueva tarea. ¿Cuál es el título?')

# --- Controlador de Mensajes para los Pasos del Flujo de Trabajo ---

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Maneja todos los mensajes entrantes y los dirige según el estado del usuario."""
 user_id = update.effective_user.id
 text = update.message.text

 current_state = user_states.get(user_id, {'current_step': STATE_NONE})['current_step']
 task_data = user_states.get(user_id, {'task_data': {}})['task_data']

 if current_state == STATE_AWAITING_TITLE:
 task_data['title'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_AWAITING_DESCRIPTION
 await update.message.reply_text(f'Entendido. Título: "{text}". Ahora, por favor proporciona una descripción para la tarea.')
 
 elif current_state == STATE_AWAITING_DESCRIPTION:
 task_data['description'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_NONE # Restablecer estado
 
 # Aquí normalmente guardarías task_data en una base de datos o archivo
 await update.message.reply_text(
 f'¡Tarea creada!\nTítulo: {task_data["title"]}\nDescripción: {task_data["description"]}\n\n'
 f'Puedes comenzar una nueva tarea con /new_task.'
 )
 # Limpiar datos de tarea para este usuario
 user_states[user_id]['task_data'] = {}
 
 else:
 # Si no hay un flujo de trabajo específico activo, responde con un mensaje predeterminado
 await update.message.reply_text('No entiendo eso. Intenta /new_task para empezar a crear una tarea.')

# --- Configuración Principal del Bot ---

def main() -> None:
 """Inicia el bot."""
 application = Application.builder().token(BOT_TOKEN).build()

 # Registrar controladores
 application.add_handler(CommandHandler("start", start))
 application.add_handler(CommandHandler("new_task", new_task))
 application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))

 # Ejecuta el bot hasta que el usuario presione Ctrl-C
 application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
 main()

Algunas cosas a tener en cuenta aquí:

  • user_states: Este diccionario es nuestra simple máquina de estados. Cada ID de usuario se relaciona con su paso actual y cualquier dato recopilado.
  • Los comandos start y new_task: Estos inician o restablecen el estado. new_task establece específicamente el estado del usuario en STATE_AWAITING_TITLE.
  • handle_message: Este es el caballo de batalla. Verifica el estado actual del usuario y actúa en consecuencia. Si STATE_AWAITING_TITLE, asume que el mensaje es el título. Si STATE_AWAITING_DESCRIPTION, asume que el mensaje es la descripción. Después de recopilar toda la información, restablece el estado a STATE_NONE.
  • filters.TEXT & ~filters.COMMAND: Esto es crucial para handle_message. Asegura que este controlador solo procese mensajes de texto simples que NO sean comandos (como /start o /new_task), evitando conflictos con nuestros controladores de comandos.

Agregando un Toque de Interactividad: Teclados En Línea para Confirmación

En lugar de solo pedir una descripción, ¿y si quisiéramos preguntar por un nivel de prioridad, y darle al usuario opciones predefinidas? Aquí es donde los Teclados En Línea de Telegram brillan. Aparecen directamente adjuntos a un mensaje y envían “datos de callback” cuando se tocan, en lugar de un mensaje completo.

Modifiquemos nuestro flujo de trabajo para preguntar por la prioridad utilizando un teclado en línea después de la descripción.


from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, CallbackQueryHandler, filters, ContextTypes

# ... (BOT_TOKEN, user_states, STATE_NONE, STATE_AWAITING_TITLE, STATE_AWAITING_DESCRIPTION) ...

STATE_AWAITING_PRIORITY = 3 # Nuevo estado

# ... (start, new_task commands remain the same) ...

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 user_id = update.effective_user.id
 text = update.message.text

 current_state = user_states.get(user_id, {'current_step': STATE_NONE})['current_step']
 task_data = user_states.get(user_id, {'task_data': {}})['task_data']

 if current_state == STATE_AWAITING_TITLE:
 task_data['title'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_AWAITING_DESCRIPTION
 await update.message.reply_text(f'Entendido. Título: "{text}". Ahora, por favor proporciona una descripción para la tarea.')
 
 elif current_state == STATE_AWAITING_DESCRIPTION:
 task_data['description'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_AWAITING_PRIORITY # Mover a nuevo estado
 
 keyboard = [
 [InlineKeyboardButton("Alto", callback_data="priority_high")],
 [InlineKeyboardButton("Medio", callback_data="priority_medium")],
 [InlineKeyboardButton("Bajo", callback_data="priority_low")],
 ]
 reply_markup = InlineKeyboardMarkup(keyboard)
 await update.message.reply_text('¡Gracias por la descripción! ¿Cuál es la prioridad para esta tarea?', reply_markup=reply_markup)
 
 else:
 await update.message.reply_text('No entiendo eso. Intenta /new_task para comenzar a crear una tarea.')

async def handle_callback_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Maneja las pulsaciones de los botones del teclado en línea."""
 query = update.callback_query
 await query.answer() # Siempre responde a las consultas de devolución de llamada, incluso si está vacío

 user_id = query.from_user.id
 data = query.data # Este es el callback_data que definimos en los botones

 current_state = user_states.get(user_id, {'current_step': STATE_NONE})['current_step']
 task_data = user_states.get(user_id, {'task_data': {}})['task_data']

 if current_state == STATE_AWAITING_PRIORITY and data.startswith('priority_'):
 task_data['priority'] = data.split('_')[1] # Extraer 'high', 'medium', 'low'
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_NONE # Restablecer estado
 
 # Editar el mensaje para remover el teclado y mostrar confirmación
 await query.edit_message_text(
 f'¡Tarea creada!\nTítulo: {task_data["title"]}\nDescripción: {task_data["description"]}\n'
 f'Prioridad: {task_data["priority"].capitalize()}\n\nPuedes comenzar una nueva tarea con /new_task.'
 )
 # Limpiar datos de tarea para este usuario
 user_states[user_id]['task_data'] = {}
 else:
 await query.edit_message_text('Algo salió mal o tu sesión expiró. Por favor, comienza de nuevo con /new_task.')

# --- Configuración principal del bot (actualizada) ---

def main() -> None:
 application = Application.builder().token(BOT_TOKEN).build()

 application.add_handler(CommandHandler("start", start))
 application.add_handler(CommandHandler("new_task", new_task))
 application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
 application.add_handler(CallbackQueryHandler(handle_callback_query)) # Nuevo manejador para botones en línea

 application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
 main()

Las adiciones clave aquí son:

  • STATE_AWAITING_PRIORITY: Un nuevo estado para gestionar.
  • InlineKeyboardButton y InlineKeyboardMarkup: Utilizados para construir los botones interactivos.
  • callback_data: Una cadena asociada a cada botón. Esto es lo que se envía de vuelta a tu bot cuando se presiona el botón. Está limitado a 64 bytes, así que manténlo conciso.
  • CallbackQueryHandler: Un nuevo tipo de manejador en nuestra configuración principal, específicamente para escuchar estas pulsaciones de botones en línea.
  • query.answer(): Importante para la experiencia del usuario. Telegram espera una respuesta rápida a una consulta de devolución de llamada, incluso si es vacía, para mostrar al usuario que su toque fue registrado.
  • query.edit_message_text(): En lugar de enviar un nuevo mensaje, actualizamos el existente. Esto hace que la conversación fluya de manera mucho más limpia, ya que el teclado en línea desaparece una vez que se hace una elección.

Este enfoque transforma una serie de mensajes de texto que podrían ser engorrosos en una experiencia mucho más intuitiva y amigable. Imagina expandir esto para seleccionar categorías, fechas de un selector de calendario (usando más botones en línea), o confirmar acciones antes de que se ejecuten.

Conclusiones Accionables para Tu Próximo Proyecto de Bot

  1. Adopta la Gestión de Estado Temprano: Para cualquier cosa más allá de bots de un solo comando, *necesitarás* rastrear el estado del usuario. Comienza simple con un diccionario, pero planifica para la persistencia si tu bot necesita recordar conversaciones a través de reinicios.
  2. Utiliza los Elementos de UI de Telegram: Los teclados en línea y los teclados de respuesta personalizados son increíblemente poderosos para guiar a los usuarios, ofrecer opciones y simplificar la entrada. No hagas que los usuarios escriban todo si puedes ofrecer un botón.
  3. Modulariza Tus Manejadores: A medida que tu bot crece, separa tu lógica en funciones distintas o incluso módulos. Una enorme función handle_message rápidamente se vuelve inmanejable.
  4. Maneja Casos Límites y Reinicios: ¿Qué pasa si un usuario escribe /new_task en medio de otro flujo de trabajo? ¿Qué pasa si simplemente dejan de responder? Implementa formas de reiniciar las conversaciones con gracia o de invitarlos de nuevo al flujo. Mi ejemplo maneja esto implícitamente reiniciando el estado con /new_task.
  5. Prueba, Prueba, Prueba: Utiliza un bot de prueba (de BotFather) para el desarrollo. Prueba diferentes flujos de usuarios, entradas inesperadas y uso concurrente.

La API de Bot de Telegram, especialmente con bibliotecas como python-telegram-bot, proporciona un playground fantástico para construir aplicaciones interactivas. Ya no es solo para enviar fotos de gatos; puedes construir herramientas verdaderamente útiles con sorprendentemente poco esfuerzo. Así que avanza, experimenta con estos conceptos y construye algo genial!

Artículos Relacionados

🕒 Published:

💬
Written by Jake Chen

Bot developer who has built 50+ chatbots across Discord, Telegram, Slack, and WhatsApp. Specializes in conversational AI and NLP.

Learn more →
Browse Topics: Best Practices | Bot Building | Bot Development | Business | Operations
Scroll to Top