refactor: Migrate bot core and modules from talia_bot to bot directory, update start_bot.sh and Dockerfile, and modify README.md.

This commit is contained in:
Marco Gallegos
2025-12-21 18:00:31 -06:00
parent 6e1a2f0102
commit 13141d6ed3
38 changed files with 112 additions and 86 deletions

View File

@@ -8,8 +8,8 @@ WORKDIR /talia_bot
COPY requirements.txt . COPY requirements.txt .
RUN pip install -r requirements.txt RUN pip install -r requirements.txt
# Copy app code # Copy the package contents
COPY talia_bot/ . COPY bot bot
# Run the bot # Run the bot via the package entrypoint
CMD ["python", "main.py"] CMD ["python", "-m", "bot.main"]

View File

@@ -8,11 +8,11 @@ Talia es un **Middleware de Inteligencia Artificial** diseñado para orquestar o
El bot opera como un agente que sigue un ciclo de **Recepción -> Identificación -> Enrutamiento -> Ejecución**. El bot opera como un agente que sigue un ciclo de **Recepción -> Identificación -> Enrutamiento -> Ejecución**.
1. **Recepción de Mensajes**: `main.py` actúa como el punto de entrada que recibe todos los inputs (texto, botones, comandos, documentos) desde Telegram. 1. **Recepción de Mensajes**: `bot/main.py` actúa como el punto de entrada que recibe todos los inputs (texto, botones, comandos, documentos) desde Telegram.
2. **Identificación de Usuario**: Al recibir un mensaje, el módulo `identity.py` consulta la base de datos (`users.db`) para obtener el rol del usuario (`admin`, `crew`, `client`). 2. **Identificación de Usuario**: Al recibir un mensaje, el módulo `identity.py` consulta la base de datos (`users.db`) para obtener el rol del usuario (`admin`, `crew`, `client`).
3. **Enrutamiento de Acciones**: 3. **Enrutamiento de Acciones**:
* **Si el usuario está en una conversación activa**, el `flow_engine.py` toma el control y procesa la respuesta según la definición del flujo JSON correspondiente. * **Si el usuario está en una conversación activa**, el `flow_engine.py` toma el control y procesa la respuesta según la definición del flujo JSON correspondiente.
* **Si el usuario no está en una conversación**, el sistema le muestra un menú de botones. Estos menús se generan dinámicamente a partir de los archivos de flujo en `talia_bot/data/flows/` que tienen una clave `"trigger_button"`. * **Si el usuario no está en una conversación**, el sistema le muestra un menú de botones. Estos menús se generan dinámicamente a partir de los archivos de flujo en `bot/data/flows/` que tienen una clave `"trigger_button"`.
4. **Ejecución de Módulos**: Dependiendo de la acción, se invocan módulos específicos para interactuar con APIs externas: 4. **Ejecución de Módulos**: Dependiendo de la acción, se invocan módulos específicos para interactuar con APIs externas:
* `sales_rag.py` para generar respuestas de ventas con IA. * `sales_rag.py` para generar respuestas de ventas con IA.
* `printer.py` para enviar correos de impresión. * `printer.py` para enviar correos de impresión.
@@ -116,9 +116,9 @@ GOOGLE_SERVICE_ACCOUNT_FILE=./google_key.json
* **Base de Datos**: La base de datos `users.db` se creará automáticamente si no existe. Para asignar roles, debes agregar manualmente los Telegram IDs en la tabla `users`. * **Base de Datos**: La base de datos `users.db` se creará automáticamente si no existe. Para asignar roles, debes agregar manualmente los Telegram IDs en la tabla `users`.
* **Credenciales de Google**: Coloca tu archivo de credenciales de la cuenta de servicio de Google Cloud en el directorio raíz del proyecto y renómbralo a `google_key.json`. **El archivo `.gitignore` ya está configurado para ignorar este archivo y proteger tus claves.** * **Credenciales de Google**: Coloca tu archivo de credenciales de la cuenta de servicio de Google Cloud en el directorio raíz del proyecto y renómbralo a `google_key.json`. **El archivo `.gitignore` ya está configurado para ignorar este archivo y proteger tus claves.**
* **Flujos de Conversación**: Para modificar o añadir flujos, edita los archivos JSON en `talia_bot/data/flows/`. * **Flujos de Conversación**: Para modificar o añadir flujos, edita los archivos JSON en `bot/data/flows/`.
Asegúrate de tener los archivos y directorios base en `talia_bot/data/`: Asegúrate de tener los archivos y directorios base en `bot/data/`:
* `servicios.json`: Catálogo de servicios para el RAG de ventas. * `servicios.json`: Catálogo de servicios para el RAG de ventas.
* `credentials.json`: Credenciales de Google Cloud. * `credentials.json`: Credenciales de Google Cloud.
* `users.db`: Base de datos SQLite que almacena los roles de los usuarios. * `users.db`: Base de datos SQLite que almacena los roles de los usuarios.
@@ -136,28 +136,37 @@ talia_bot/
├── Dockerfile # Define el contenedor de la aplicación ├── Dockerfile # Define el contenedor de la aplicación
├── docker-compose.yml # Orquesta el servicio del bot ├── docker-compose.yml # Orquesta el servicio del bot
├── google_key.json # (Local) Credenciales de Google Cloud ├── google_key.json # (Local) Credenciales de Google Cloud
├── plan_de_pruebas.md # Casos de prueba documentados
├── README.md # Documentación principal
├── requirements.txt # Dependencias de Python ├── requirements.txt # Dependencias de Python
├── talia_bot/ ├── start_bot.sh # Script para iniciar el bot en desarrollo
│ ├── main.py # Entry Point y dispatcher principal └── bot/
├── db.py # Gestión de la base de datos SQLite ├── __init__.py # Inicializador de paquete
├── config.py # Carga de variables de entorno ├── main.py # Entry point y dispatcher principal
├── modules/ ├── db.py # Gestión de la base de datos SQLite
│ │ ├── flow_engine.py # Motor de flujos de conversación (lee los JSON) ├── config.py # Carga de variables de entorno
│ │ ├── identity.py # Lógica de Roles y Permisos ├── scheduler.py # Tareas programadas y resúmenes diarios
│ │ ├── llm_engine.py # Cliente OpenAI/Gemini ├── webhook_client.py # Webhooks externos (n8n, etc.)
│ │ ├── vikunja.py # API Manager para Tareas ├── modules/
│ ├── calendar.py # Google Calendar Logic & Rules │ ├── flow_engine.py # Motor de flujos de conversación
│ ├── printer.py # SMTP/IMAP Loop │ ├── identity.py # Lógica de Roles y Permisos
── sales_rag.py # Lógica de Ventas y Servicios ── llm_engine.py # Cliente OpenAI/Gemini
── data/ ── vikunja.py # API Manager para tareas
├── flows/ # Directorio con los flujos de conversación en JSON ├── calendar.py # Google Calendar Logic & Rules
├── servicios.json # Base de conocimiento para ventas ├── agenda.py # Agendas y solicitudes
├── credentials.json # Credenciales de Google ├── printer.py # SMTP/IMAP Loop
── users.db # Base de datos de usuarios ── sales_rag.py # Lógica de Ventas y Servicios
├── .env.example # Plantilla de variables de entorno │ ├── debug.py # Herramientas de diagnóstico
├── requirements.txt # Dependencias │ ├── onboarding.py # Menús y onboarding inicial
├── Dockerfile # Configuración del contenedor │ ├── citas.py # Solicitudes de citas
└── docker-compose.yml # Orquestador de Docker │ ├── nfc_tag.py # Wizard NFC
│ ├── aprobaciones.py # Aprobaciones y rechazos
│ └── equipo.py # Equipo y estado de solicitudes
└── data/
├── flows/ # Directorio con los flujos de conversación JSON
├── servicios.json # Base de conocimiento para ventas
├── credentials.json # Credenciales de Google
└── users.db # Base de datos de usuarios
``` ```
--- ---

2
bot/__init__.py Normal file
View File

@@ -0,0 +1,2 @@
# bot/__init__.py
# Package initializer for the bot application.

View File

@@ -1,4 +1,4 @@
# talia_bot/config.py # bot/config.py
# This file loads all environment variables and bot configurations. # This file loads all environment variables and bot configurations.
# Environment variables are stored securely outside the code (e.g., in a .env file). # Environment variables are stored securely outside the code (e.g., in a .env file).

View File

@@ -1,4 +1,4 @@
# talia_bot/db.py # bot/db.py
# This module will handle the database connection and operations. # This module will handle the database connection and operations.
import sqlite3 import sqlite3

View File

@@ -1,8 +1,10 @@
# talia_bot/main.py # bot/main.py
# Este es el archivo principal del bot. Aquí se inicia todo y se configuran los comandos. # Este es el archivo principal del bot. Aquí se inicia todo y se configuran los comandos.
import logging import logging
import asyncio import asyncio
import sys
from pathlib import Path
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ( from telegram.ext import (
Application, Application,
@@ -15,27 +17,34 @@ from telegram.ext import (
TypeHandler, TypeHandler,
) )
# Ensure package imports work even if the file is executed directly
if __package__ is None:
current_dir = Path(__file__).resolve().parent
project_root = current_dir.parent
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
# Importamos las configuraciones y herramientas que creamos en otros archivos # Importamos las configuraciones y herramientas que creamos en otros archivos
from talia_bot.config import TELEGRAM_BOT_TOKEN from bot.config import TELEGRAM_BOT_TOKEN
from talia_bot.modules.identity import get_user_role from bot.modules.identity import get_user_role
from talia_bot.modules.onboarding import handle_start as onboarding_handle_start from bot.modules.onboarding import handle_start as onboarding_handle_start
from talia_bot.modules.onboarding import get_admin_secondary_menu from bot.modules.onboarding import get_admin_secondary_menu
from talia_bot.modules.agenda import get_agenda from bot.modules.agenda import get_agenda
from talia_bot.modules.citas import request_appointment from bot.modules.citas import request_appointment
from talia_bot.modules.equipo import ( from bot.modules.equipo import (
view_requests_status, view_requests_status,
) )
from talia_bot.modules.aprobaciones import view_pending, handle_approval_action from bot.modules.aprobaciones import view_pending, handle_approval_action
from talia_bot.modules.admin import get_system_status from bot.modules.admin import get_system_status
import os import os
from talia_bot.modules.debug import print_handler from bot.modules.debug import print_handler
from talia_bot.modules.vikunja import vikunja_conv_handler, get_projects_list, get_tasks_list from bot.modules.vikunja import vikunja_conv_handler, get_projects_list, get_tasks_list
from talia_bot.modules.printer import send_file_to_printer, check_print_status from bot.modules.printer import send_file_to_printer, check_print_status
from talia_bot.db import setup_database from bot.db import setup_database
from talia_bot.modules.flow_engine import FlowEngine from bot.modules.flow_engine import FlowEngine
from talia_bot.modules.llm_engine import transcribe_audio from bot.modules.llm_engine import transcribe_audio
from talia_bot.scheduler import schedule_daily_summary from bot.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
logging.basicConfig( logging.basicConfig(
@@ -314,4 +323,4 @@ def main() -> None:
application.run_polling() application.run_polling()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -1,11 +1,11 @@
# talia_bot/modules/agenda.py # bot/modules/agenda.py
# Este módulo se encarga de manejar las peticiones relacionadas con la agenda. # Este módulo se encarga de manejar las peticiones relacionadas con la agenda.
# Permite obtener y mostrar las actividades programadas para el día. # Permite obtener y mostrar las actividades programadas para el día.
import datetime import datetime
import logging import logging
from talia_bot.modules.calendar import get_events from bot.modules.calendar import get_events
from talia_bot.config import WORK_GOOGLE_CALENDAR_ID, PERSONAL_GOOGLE_CALENDAR_ID from bot.config import WORK_GOOGLE_CALENDAR_ID, PERSONAL_GOOGLE_CALENDAR_ID
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -7,7 +7,7 @@ import logging
from google.oauth2 import service_account from google.oauth2 import service_account
from googleapiclient.discovery import build from googleapiclient.discovery import build
from googleapiclient.errors import HttpError from googleapiclient.errors import HttpError
from talia_bot.config import GOOGLE_SERVICE_ACCOUNT_FILE, WORK_GOOGLE_CALENDAR_ID from bot.config import GOOGLE_SERVICE_ACCOUNT_FILE, WORK_GOOGLE_CALENDAR_ID
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -2,7 +2,7 @@
# Este módulo maneja la programación de citas para los clientes. # Este módulo maneja la programación de citas para los clientes.
# Permite a los usuarios obtener un enlace para agendar una reunión. # Permite a los usuarios obtener un enlace para agendar una reunión.
from talia_bot.config import CALENDLY_LINK from bot.config import CALENDLY_LINK
def request_appointment(): def request_appointment():
""" """

View File

@@ -1,11 +1,16 @@
# talia_bot/modules/debug.py # bot/modules/debug.py
# Este módulo permite a los administradores imprimir los detalles de configuración del bot. # Este módulo permite a los administradores imprimir los detalles de configuración del bot.
# Es una herramienta útil para depuración (debugging). # Es una herramienta útil para depuración (debugging).
from telegram import Update from telegram import Update
from telegram.ext import ContextTypes from telegram.ext import ContextTypes
from talia_bot.modules.identity import is_admin from bot.modules.identity import is_admin
from talia_bot.config import TIMEZONE, CALENDAR_ID, N8N_WEBHOOK_URL from bot.config import (
TIMEZONE,
WORK_GOOGLE_CALENDAR_ID,
PERSONAL_GOOGLE_CALENDAR_ID,
N8N_WEBHOOK_URL,
)
async def print_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def print_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
""" """
@@ -21,8 +26,9 @@ async def print_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N
config_details = ( config_details = (
f"**Detalles de Configuración**\n" f"**Detalles de Configuración**\n"
f"Zona Horaria: `{TIMEZONE}`\n" f"Zona Horaria: `{TIMEZONE}`\n"
f"ID de Calendario: `{CALENDAR_ID}`\n" f"Calendario Trabajo: `{WORK_GOOGLE_CALENDAR_ID or 'No definido'}`\n"
f"URL Webhook n8n: `{N8N_WEBHOOK_URL}`\n" f"Calendario Personal: `{PERSONAL_GOOGLE_CALENDAR_ID or 'No definido'}`\n"
f"URL Webhook n8n: `{N8N_WEBHOOK_URL or 'No definido'}`\n"
) )
await update.message.reply_text(config_details, parse_mode='Markdown') await update.message.reply_text(config_details, parse_mode='Markdown')
else: else:

View File

@@ -1,10 +1,10 @@
# talia_bot/modules/flow_engine.py # bot/modules/flow_engine.py
import json import json
import logging import logging
import os import os
from talia_bot.db import get_db_connection from bot.db import get_db_connection
from talia_bot.modules.sales_rag import generate_sales_pitch from bot.modules.sales_rag import generate_sales_pitch
from talia_bot.modules.nfc_tag import generate_nfc_tag from bot.modules.nfc_tag import generate_nfc_tag
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -14,7 +14,7 @@ class FlowEngine:
def _load_flows(self): def _load_flows(self):
"""Loads all individual flow JSON files from the flows directory.""" """Loads all individual flow JSON files from the flows directory."""
# flows_dir = 'talia_bot/data/flows' # OLD # flows_dir = 'bot/data/flows' # OLD
base_dir = os.path.dirname(os.path.abspath(__file__)) base_dir = os.path.dirname(os.path.abspath(__file__))
flows_dir = os.path.join(base_dir, '..', 'data', 'flows') flows_dir = os.path.join(base_dir, '..', 'data', 'flows')

View File

@@ -1,9 +1,9 @@
# talia_bot/modules/identity.py # bot/modules/identity.py
# Este script maneja los roles y permisos de los usuarios. # Este script maneja los roles y permisos de los usuarios.
import logging import logging
from talia_bot.db import get_db_connection from bot.db import get_db_connection
from talia_bot.config import ADMIN_ID from bot.config import ADMIN_ID
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -1,8 +1,8 @@
# talia_bot/modules/llm_engine.py # bot/modules/llm_engine.py
# Este script se encarga de la comunicación con la inteligencia artificial de OpenAI. # Este script se encarga de la comunicación con la inteligencia artificial de OpenAI.
import openai import openai
from talia_bot.config import OPENAI_API_KEY, OPENAI_MODEL from bot.config import OPENAI_API_KEY, OPENAI_MODEL
def get_smart_response(prompt): def get_smart_response(prompt):
""" """

View File

@@ -1,4 +1,4 @@
# talia_bot/modules/nfc_tag.py # bot/modules/nfc_tag.py
# This module contains the logic for generating NFC tags. # This module contains the logic for generating NFC tags.
import base64 import base64

View File

@@ -1,4 +1,4 @@
# talia_bot/modules/onboarding.py # bot/modules/onboarding.py
# Este módulo maneja la primera interacción con el usuario (el comando /start). # Este módulo maneja la primera interacción con el usuario (el comando /start).
# Se encarga de mostrar un menú diferente según quién sea el usuario (admin, crew o cliente). # Se encarga de mostrar un menú diferente según quién sea el usuario (admin, crew o cliente).

View File

@@ -1,4 +1,4 @@
# talia_bot/modules/printer.py # bot/modules/printer.py
# This module will contain the SMTP/IMAP loop for the remote printing service. # This module will contain the SMTP/IMAP loop for the remote printing service.
import smtplib import smtplib
@@ -10,7 +10,7 @@ from email.mime.text import MIMEText
from email.mime.base import MIMEBase from email.mime.base import MIMEBase
from email import encoders from email import encoders
from talia_bot.config import ( from bot.config import (
SMTP_SERVER, SMTP_SERVER,
SMTP_PORT, SMTP_PORT,
SMTP_USER, SMTP_USER,
@@ -20,7 +20,7 @@ from talia_bot.config import (
IMAP_PASS, IMAP_PASS,
PRINTER_EMAIL, PRINTER_EMAIL,
) )
from talia_bot.modules.identity import is_admin from bot.modules.identity import is_admin
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -1,16 +1,16 @@
# talia_bot/modules/sales_rag.py # bot/modules/sales_rag.py
# This module will contain the sales RAG flow for new clients. # This module will contain the sales RAG flow for new clients.
import json import json
import logging import logging
from talia_bot.modules.llm_engine import get_smart_response from bot.modules.llm_engine import get_smart_response
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def load_services_data(): def load_services_data():
"""Loads the services data from the JSON file.""" """Loads the services data from the JSON file."""
try: try:
with open("talia_bot/data/services.json", "r", encoding="utf-8") as f: with open("bot/data/services.json", "r", encoding="utf-8") as f:
return json.load(f) return json.load(f)
except FileNotFoundError: except FileNotFoundError:
logger.error("El archivo services.json no fue encontrado.") logger.error("El archivo services.json no fue encontrado.")

View File

@@ -13,8 +13,8 @@ from telegram.ext import (
ContextTypes, ContextTypes,
) )
from talia_bot.config import VIKUNJA_API_URL, VIKUNJA_API_TOKEN from bot.config import VIKUNJA_API_URL, VIKUNJA_API_TOKEN
from talia_bot.modules.identity import is_admin from bot.modules.identity import is_admin
# Configuración del logger # Configuración del logger
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -9,8 +9,8 @@ from datetime import time
from telegram.ext import ContextTypes from telegram.ext import ContextTypes
import pytz import pytz
from talia_bot.config import ADMIN_ID, TIMEZONE, DAILY_SUMMARY_TIME from bot.config import ADMIN_ID, TIMEZONE, DAILY_SUMMARY_TIME
from talia_bot.modules.agenda import get_agenda from bot.modules.agenda import get_agenda
# Configuramos el registro de eventos (logging) para ver qué pasa en la consola # Configuramos el registro de eventos (logging) para ver qué pasa en la consola
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -3,7 +3,7 @@
# En este caso, se comunica con n8n. # En este caso, se comunica con n8n.
import requests import requests
from talia_bot.config import N8N_WEBHOOK_URL, N8N_TEST_WEBHOOK_URL from bot.config import N8N_WEBHOOK_URL, N8N_TEST_WEBHOOK_URL
def send_webhook(event_data): def send_webhook(event_data):
""" """

View File

@@ -4,8 +4,8 @@
# Get the directory of the script # Get the directory of the script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Set PYTHONPATH to include the parent directory # Ensure the project root is on PYTHONPATH so absolute imports resolve
export PYTHONPATH="$PYTHONPATH:$DIR/.." export PYTHONPATH="$DIR:${PYTHONPATH}"
# Run the bot # Run the bot using the package entrypoint
python3 "$DIR/talia_bot/main.py" python3 -m bot.main