diff --git a/.env.example b/.env.example index 6c97a4e..3cb8950 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,18 @@ +# --- TELEGRAM & SECURITY --- TELEGRAM_BOT_TOKEN= -OWNER_CHAT_ID= -ADMIN_CHAT_IDS= -TEAM_CHAT_IDS= -GOOGLE_SERVICE_ACCOUNT_FILE= -CALENDAR_ID= -N8N_WEBHOOK_URL= +ADMIN_ID= + +# --- AI CORE --- OPENAI_API_KEY= -OPENAI_MODEL=gpt-3.5-turbo -DAILY_SUMMARY_TIME=07:00 -CALENDLY_LINK=https://calendly.com/user/appointment-link -TIMEZONE=America/Mexico_City + +# --- INTEGRATIONS --- +VIKUNJA_API_URL=https://tuservidor.com/api/v1 +VIKUNJA_TOKEN= +GOOGLE_CREDENTIALS_PATH=./data/credentials.json + +# --- PRINT SERVICE --- +SMTP_SERVER=smtp.hostinger.com +SMTP_PORT=465 +SMTP_USER=print.service@vanityexperience.mx +SMTP_PASS= +IMAP_SERVER=imap.hostinger.com diff --git a/Dockerfile b/Dockerfile index ba2dbc1..08cade8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,14 +2,14 @@ FROM python:3.9-slim # Set working directory -WORKDIR /app +WORKDIR /talia_bot # Copy and install requirements COPY requirements.txt . RUN pip install -r requirements.txt # Copy app code -COPY app/ . +COPY talia_bot/ . # Run the bot CMD ["python", "main.py"] diff --git a/README.md b/README.md index f3c5e9c..206299f 100644 --- a/README.md +++ b/README.md @@ -1,257 +1,165 @@ -# Talía — Asistente Ejecutiva Inteligente +# 🤖 Talia Bot: Asistente Personal & Orquestador de Negocio -Talía es una asistente ejecutiva digital diseñada para centralizar, ordenar y coordinar la agenda, solicitudes y actividades de Marco. Funciona como un **punto único de entrada** para clientes, equipo y administradores, asegurando que cada solicitud se procese con contexto, validación y respeto por el tiempo disponible. - -Talía no improvisa ni asume. **Consulta, valida, confirma y ejecuta.** +Talia no es un simple chatbot; es un Middleware de Inteligencia Artificial alojado en un VPS que orquesta las operaciones diarias de administración, logística y ventas. Actúa como el puente central entre usuarios en Telegram y servicios críticos como Vikunja (Gestión de Proyectos), Google Calendar y Hardware de Impresión remota. --- -## 🎯 Propósito del Sistema +## 🚀 Concepto Central: Enrutamiento por Identidad -Talía existe para eliminar fricción operativa y proteger el tiempo ejecutivo. El sistema está diseñado para: +La característica core de Talia es su capacidad de cambiar de personalidad y permisos dinámicamente basándose en el Telegram ID del usuario: -* Centralizar todas las solicitudes de agenda, citas y actividades -* Validar disponibilidad real antes de comprometer tiempo -* Priorizar clientes sin romper compromisos existentes -* Delegar reglas de negocio y disponibilidad a flujos en n8n -* Mantener trazabilidad completa mediante eventos webhook -* Escalar de forma modular sin romper flujos existentes +| Rol | Icono | Descripción | Permisos | +| :------ | :---: | :------------------ | :-------------------------------------------------------------------------------- | +| **Admin** | 👑 | Dueño / Gerente | God Mode: Gestión total de proyectos, bloqueos de calendario, generación de identidad NFC e impresión. | +| **Crew** | 👷 | Equipo Operativo | Limitado: Solicitud de agenda (validada), asignación de tareas, impresión de documentos. | +| **Cliente** | 👤 | Usuario Público | Ventas: Embudo de captación, consulta de servicios (RAG) y agendamiento comercial. | --- -## 🧠 Personalidad, Actitud y Voz +## 🛠️ Arquitectura Técnica -Talía se comporta como una asistente ejecutiva profesional: +El sistema sigue un flujo modular: -* Educada, clara y precisa en cada respuesta -* Proactiva, pero nunca invasiva -* Siempre confirma antes de agendar o ejecutar acciones -* No improvisa horarios ni decisiones -* Comunica decisiones con calma, orden y neutralidad - -Talía no es informal, no es robótica y no utiliza sarcasmo. Su función es **ordenar el día, no interrumpirlo**. +1. **Input**: Telegram (Texto o Audio). +2. **STT**: Whisper (Conversión de Audio a Texto). +3. **Router**: Verificación de ID contra la base de datos de usuarios. +4. **Cerebro (LLM)**: OpenAI (Fase 1) / Google Gemini (Fase 2). +5. **Tools**: + * **Vikunja API**: Lectura/Escritura de tareas con filtrado de privacidad. + * **Google Calendar API**: Gestión de tiempos y reglas de disponibilidad. + * **SMTP/IMAP**: Comunicación bidireccional con impresoras. + * **NFC Gen**: Codificación Base64 para tags físicos. --- -## 👥 Roles y Niveles de Acceso +## 📋 Flujos de Trabajo (Features) -### Marco (Owner) +### 1. 👑 Gestión Admin (Proyectos & Identidad) -* Consulta agenda, pendientes y solicitudes activas -* Recibe resumen diario automático a las 7:00 AM -* Aprueba o rechaza solicitudes del equipo -* Puede interactuar desde su número privado -* Tiene prioridad absoluta sobre cualquier decisión +* **Proyectos (Vikunja)**: + * Resumen inteligente de estatus de proyectos. + * Comandos naturales: *"Marca el proyecto de web como terminado y comenta que se envió factura"*. +* **Wizard de Identidad (NFC)**: + * Flujo paso a paso para dar de alta colaboradores. + * Genera JSON de registro y String Base64 listo para escribir en Tags NFC. + * Inputs: Nombre, ID Empleado, Sucursal (Botones), Telegram ID. -### Clientes +### 2. 👷 Gestión Crew (Agenda & Tareas) -* Solicitan citas de duración fija (30 minutos) -* Visualizan únicamente horarios disponibles -* No tienen acceso a la agenda completa +* **Solicitud de Tiempo (Wizard)**: + * Solicita espacios de 1 a 4 horas. + * **Reglas de Negocio**: + * No permite fechas > 3 meses a futuro. + * **Gatekeeper**: Verifica Google Calendar. Si hay evento "Privado" del Admin, rechaza automáticamente. +* **Modo Buzón (Vikunja)**: + * Crea tareas asignadas al Admin. + * **Privacidad**: Solo pueden consultar el estatus de tareas creadas por ellos mismos. -### Equipo Autorizado +### 3. 🖨️ Sistema de Impresión Remota (Print Loop) -* Puede proponer actividades de mayor duración (ej. grabaciones) -* Puede solicitar acciones operativas -* Toda actividad que consuma tiempo requiere aprobación +* Permite enviar archivos desde Telegram a la impresora física de la oficina. +* **Envío (SMTP)**: El bot envía el documento a un correo designado. +* **Tracking**: El asunto del correo lleva un hash único: `PJ:{uuid}#TID:{telegram_id}`. +* **Confirmación (IMAP Listener)**: Un proceso en background escucha la respuesta de la impresora y notifica al usuario en Telegram. -### Administradores +### 4. 👤 Ventas Automáticas (RAG) -* Ejecutan acciones sensibles -* Requieren validación adicional -* Acceden a flujos administrativos restringidos +* Identifica usuarios nuevos (no registrados en la DB). +* Captura datos (Lead Magnet). +* Analiza ideas de clientes usando `servicios.json` (Base de conocimiento). +* Ofrece citas de ventas mediante link de Calendly. --- -## 🏗️ Arquitectura del Sistema +## ⚙️ Instalación y Configuración -Talía está construida en capas desacopladas que se comunican por eventos: +### Prerrequisitos -1. **Interfaz Conversacional** – Telegram / WhatsApp -2. **Cerebro Central** – Python -3. **Automatización y Reglas** – n8n -4. **Servicios Externos** – Google Calendar, IA, APIs +* Python 3.10+ +* Cuenta de Telegram Bot (@BotFather) +* Instancia de Vikunja (Self-hosted) +* Cuenta de Servicio Google Cloud (Calendar API) +* Servidor de Correo (SMTP/IMAP) -Cada capa es independiente y puede evolucionar sin afectar a las demás. +### 1. Clonar y Entorno Virtual ---- - -## 📁 Estructura del Proyecto - -```text -talia-bot/ -├── docker-compose.yml # Orquestación de contenedores -├── Dockerfile # Imagen del bot -├── .env.example # Variables de entorno -├── README.md # Documentación -└── app/ - ├── main.py # Cerebro del bot - ├── config.py # Configuración y credenciales - ├── permissions.py # Roles y validaciones - ├── scheduler.py # Resumen diario y recordatorios - ├── webhook_client.py # Comunicación con n8n - ├── calendar.py # Integración Google Calendar - ├── llm.py # Respuestas inteligentes (IA) - └── modules/ - ├── onboarding.py # Bienvenida y menú inicial - ├── agenda.py # Consulta de agenda - ├── citas.py # Citas con clientes - ├── equipo.py # Solicitudes del equipo - ├── aprobaciones.py # Aprobaciones del owner - ├── servicios.py # Servicios y cotizaciones - └── admin.py # Acciones administrativas +```bash +git clone https://github.com/marcogll/talia_bot_mg.git +cd talia_bot_mg +python -m venv venv +source venv/bin/activate # Windows: venv\Scripts\activate +pip install -r requirements.txt ``` ---- +### 2. Variables de Entorno (`.env`) -## 🧠 Cerebro del Sistema (`main.py`) - -`main.py` actúa como **orquestador central**. No contiene reglas de negocio complejas. Sus funciones son: - -* Recibir mensajes y callbacks -* Identificar usuario y rol -* Mantener contexto conversacional -* Delegar acciones a módulos -* Emitir y recibir eventos vía webhook - -Toda decisión importante se valida externamente. - ---- - -## 🧩 Módulos Funcionales - -Cada módulo cumple una responsabilidad única: - -* **onboarding.py**: inicio de conversación y opciones -* **agenda.py**: consulta de agenda y pendientes -* **citas.py**: flujo de citas con clientes -* **equipo.py**: solicitudes internas del equipo -* **aprobaciones.py**: aceptar o rechazar solicitudes -* **servicios.py**: información y cotización de proyectos -* **admin.py**: acciones administrativas -* **create_tag.py**: genera un tag de identificación en Base64 para NFC -* **print.py**: (admin) imprime la configuración actual del bot - ---- - -## ⚡ 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 - -1. Usuario envía mensaje o interactúa con botones -2. Talía valida identidad y permisos -3. Se ejecuta el módulo correspondiente -4. Si se requiere lógica externa, se envía evento a n8n -5. n8n evalúa reglas y responde -6. Talía comunica el resultado -7. Si aplica, se agenda en Google Calendar - ---- - -## 📆 Gestión de Agenda - -### Citas con Clientes - -* Duración fija: 30 minutos -* Disponibilidad definida exclusivamente por n8n -* Confirmación explícita antes de agendar - -### Actividades del Equipo - -* Duración flexible -* Requieren aprobación del owner -* Solo usuarios autorizados pueden solicitarlas - ---- - -## ⏰ Resumen Diario - -Todos los días a las **7:00 AM**, Talía envía a Marco: - -* Agenda del día -* Pendientes activos -* Recordatorios importantes - ---- - -## 🔌 Webhooks - -Toda acción relevante genera o responde un evento webhook. - -Ejemplo: - -```json -{ - "event": "request_activity", - "from": "team", - "duration_hours": 4, - "description": "Grabación de proyecto" -} -``` - ---- - -## 🔐 Variables de Entorno +Crea un archivo `.env` en la raíz con la siguiente estructura: ```env -TELEGRAM_BOT_TOKEN= -OWNER_CHAT_ID= -ADMIN_CHAT_IDS= -TEAM_CHAT_IDS= -GOOGLE_CLIENT_ID= -GOOGLE_CLIENT_SECRET= -GOOGLE_REFRESH_TOKEN= -N8N_WEBHOOK_URL= -OPENAI_API_KEY= -TIMEZONE=America/Mexico_City +# --- TELEGRAM & SECURITY --- +TELEGRAM_BOT_TOKEN=tu_token_telegram +ADMIN_ID=tu_telegram_id + +# --- AI CORE --- +OPENAI_API_KEY=sk-... + +# --- INTEGRACIONES --- +VIKUNJA_API_URL=https://tuservidor.com/api/v1 +VIKUNJA_TOKEN=tu_token_vikunja +GOOGLE_CREDENTIALS_PATH=./data/credentials.json + +# --- PRINT SERVICE --- +SMTP_SERVER=smtp.hostinger.com +SMTP_PORT=465 +SMTP_USER=print.service@vanityexperience.mx +SMTP_PASS=tu_password_seguro +IMAP_SERVER=imap.hostinger.com +``` + +### 3. Estructura de Datos + +Asegúrate de tener los archivos base en `talia_bot/data/`: +* `servicios.json`: Catálogo de servicios para el RAG de ventas. +* `credentials.json`: Credenciales de Google Cloud. +* `users.db`: Base de datos SQLite. + +--- + +## 📂 Estructura del Proyecto + +```text +talia_bot_mg/ +├── talia_bot/ +│ ├── main.py # Entry Point y Router de Identidad +│ ├── db.py # Gestión de la base de datos +│ ├── config.py # Carga de variables de entorno +│ ├── modules/ +│ │ ├── identity.py # Lógica de Roles y Permisos +│ │ ├── llm_engine.py # Cliente OpenAI/Gemini +│ │ ├── vikunja.py # API Manager para Tareas +│ │ ├── calendar.py # Google Calendar Logic & Rules +│ │ ├── printer.py # SMTP/IMAP Loop +│ │ └── sales_rag.py # Lógica de Ventas y Servicios +│ └── data/ +│ ├── servicios.json # Base de conocimiento +│ ├── credentials.json # Credenciales de Google +│ └── users.db # Base de datos de usuarios +├── .env.example # Plantilla de variables de entorno +├── requirements.txt # Dependencias +├── Dockerfile # Configuración del contenedor +└── docker-compose.yml # Orquestador de Docker ``` --- -## 🐳 Despliegue con Docker Compose +## 🗓️ Roadmap -```yaml -version: "3.9" -services: - talia-bot: - build: . - container_name: talia-bot - env_file: - - .env - restart: unless-stopped -``` +- [ ] Implementar Wizard de creación de Tags NFC (Base64). +- [ ] Conectar Loop de Impresión (SMTP/IMAP). +- [ ] Migrar de OpenAI a Google Gemini 1.5 Pro. +- [ ] Implementar soporte para fotos en impresión. --- -## 🛠️ Guía de Desarrollo - -1. Clonar el repositorio -2. Crear archivo `.env` -3. Configurar bot de Telegram -4. Configurar flujos y reglas en n8n -5. Conectar Google Calendar -6. Levantar servicios con Docker Compose - ---- - -## ✨ Principio Rector - -Talía no es un bot que responde mensajes. -Es un sistema de criterio, orden y protección del tiempo. - -Si algo no está claro, pregunta. -Si algo invade la agenda, protege. -Si algo es importante, lo prioriza. +Desarrollado por: Marco G. +Asistente Personalizado v1.0 diff --git a/app/permissions.py b/app/permissions.py deleted file mode 100644 index ce012bb..0000000 --- a/app/permissions.py +++ /dev/null @@ -1,39 +0,0 @@ -# app/permissions.py -# Este script maneja los permisos de los usuarios según su ID de chat de Telegram. - -from config import OWNER_CHAT_ID, ADMIN_CHAT_IDS, TEAM_CHAT_IDS - -def get_user_role(chat_id): - """ - Determina el rol de un usuario basado en su ID de chat. - - Roles posibles: owner (dueño), admin (administrador), team (equipo), client (cliente). - """ - chat_id_str = str(chat_id) - - # Si el ID coincide con el del dueño - if chat_id_str == OWNER_CHAT_ID: - return "owner" - - # Si el ID está en la lista de administradores - if chat_id_str in ADMIN_CHAT_IDS: - return "admin" - - # Si el ID está en la lista del equipo - if chat_id_str in TEAM_CHAT_IDS: - return "team" - - # Si no es ninguno de los anteriores, es un cliente normal - return "client" - -def is_owner(chat_id): - """Verifica si un usuario es el dueño.""" - return get_user_role(chat_id) == "owner" - -def is_admin(chat_id): - """Verifica si un usuario es administrador o dueño.""" - return get_user_role(chat_id) in ["owner", "admin"] - -def is_team_member(chat_id): - """Verifica si un usuario es parte del equipo, administrador o dueño.""" - return get_user_role(chat_id) in ["owner", "admin", "team"] diff --git a/app/config.py b/talia_bot/config.py similarity index 86% rename from app/config.py rename to talia_bot/config.py index 53669f6..6056ad0 100644 --- a/app/config.py +++ b/talia_bot/config.py @@ -1,4 +1,4 @@ -# app/config.py +# talia_bot/config.py # Este archivo se encarga de cargar todas las variables de entorno y configuraciones del bot. # Las variables de entorno son valores que se guardan fuera del código por seguridad (como tokens y llaves API). @@ -14,13 +14,7 @@ load_dotenv(dotenv_path=env_path) TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") # ID de chat del dueño del bot (para recibir notificaciones importantes) -OWNER_CHAT_ID = os.getenv("OWNER_CHAT_ID") - -# IDs de chat de los administradores, separados por comas en el archivo .env -ADMIN_CHAT_IDS = os.getenv("ADMIN_CHAT_IDS", "").split(",") - -# IDs de chat del equipo de trabajo, separados por comas -TEAM_CHAT_IDS = os.getenv("TEAM_CHAT_IDS", "").split(",") +ADMIN_ID = os.getenv("ADMIN_ID") # Ruta al archivo de credenciales de la cuenta de servicio de Google GOOGLE_SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_SERVICE_ACCOUNT_FILE") diff --git a/talia_bot/data/users.db b/talia_bot/data/users.db new file mode 100644 index 0000000..9f8d355 Binary files /dev/null and b/talia_bot/data/users.db differ diff --git a/talia_bot/db.py b/talia_bot/db.py new file mode 100644 index 0000000..a4fe64c --- /dev/null +++ b/talia_bot/db.py @@ -0,0 +1,48 @@ +# talia_bot/db.py +# This module will handle the database connection and operations. + +import sqlite3 +import logging + +DATABASE_FILE = "talia_bot/data/users.db" + +logger = logging.getLogger(__name__) + +def get_db_connection(): + """Creates a connection to the SQLite database.""" + conn = sqlite3.connect(DATABASE_FILE) + conn.row_factory = sqlite3.Row + return conn + +def setup_database(): + """Sets up the database tables if they don't exist.""" + try: + conn = get_db_connection() + cursor = conn.cursor() + + # Create the users table + cursor.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + telegram_id INTEGER UNIQUE NOT NULL, + role TEXT NOT NULL CHECK(role IN ('admin', 'crew', 'client')), + name TEXT, + employee_id TEXT, + branch TEXT + ) + """) + + conn.commit() + logger.info("Database setup complete. 'users' table is ready.") + except sqlite3.Error as e: + logger.error(f"Database error during setup: {e}") + finally: + if conn: + conn.close() + +if __name__ == '__main__': + # This allows us to run the script directly to initialize the database + logging.basicConfig(level=logging.INFO) + logger.info("Running database setup manually...") + setup_database() + logger.info("Manual setup finished.") diff --git a/app/main.py b/talia_bot/main.py similarity index 85% rename from app/main.py rename to talia_bot/main.py index cbab01a..8a453aa 100644 --- a/app/main.py +++ b/talia_bot/main.py @@ -1,4 +1,4 @@ -# app/main.py +# talia_bot/main.py # Este es el archivo principal del bot. Aquí se inicia todo y se configuran los comandos. import logging @@ -15,13 +15,13 @@ from telegram.ext import ( ) # Importamos las configuraciones y herramientas que creamos en otros archivos -from config import TELEGRAM_BOT_TOKEN -from permissions import get_user_role -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.citas import request_appointment -from modules.equipo import ( +from talia_bot.config import TELEGRAM_BOT_TOKEN +from talia_bot.modules.identity import get_user_role +from talia_bot.modules.onboarding import handle_start as onboarding_handle_start +from talia_bot.modules.onboarding import get_admin_secondary_menu +from talia_bot.modules.agenda import get_agenda +from talia_bot.modules.citas import request_appointment +from talia_bot.modules.equipo import ( propose_activity_start, get_description, get_duration, @@ -30,14 +30,15 @@ from modules.equipo import ( DESCRIPTION, DURATION, ) -from modules.aprobaciones import view_pending, handle_approval_action -from modules.servicios import get_service_info -from modules.admin import get_system_status -from modules.print import print_handler -from modules.create_tag import create_tag_conv_handler -from modules.vikunja import vikunja_conv_handler +from talia_bot.modules.aprobaciones import view_pending, handle_approval_action +from talia_bot.modules.servicios import get_service_info +from talia_bot.modules.admin import get_system_status +from talia_bot.modules.debug import print_handler +from talia_bot.modules.create_tag import create_tag_conv_handler +from talia_bot.modules.vikunja import vikunja_conv_handler +from talia_bot.db import setup_database -from scheduler import schedule_daily_summary +from talia_bot.scheduler import schedule_daily_summary # Configuramos el sistema de logs para ver mensajes de estado en la consola logging.basicConfig( @@ -124,6 +125,8 @@ def main() -> None: logger.error("TELEGRAM_BOT_TOKEN no está configurado en las variables de entorno.") return + setup_database() + application = Application.builder().token(TELEGRAM_BOT_TOKEN).build() schedule_daily_summary(application) diff --git a/app/modules/admin.py b/talia_bot/modules/admin.py similarity index 100% rename from app/modules/admin.py rename to talia_bot/modules/admin.py diff --git a/app/modules/agenda.py b/talia_bot/modules/agenda.py similarity index 95% rename from app/modules/agenda.py rename to talia_bot/modules/agenda.py index a7f4b71..3c6265c 100644 --- a/app/modules/agenda.py +++ b/talia_bot/modules/agenda.py @@ -1,10 +1,10 @@ -# app/modules/agenda.py +# talia_bot/modules/agenda.py # Este módulo se encarga de manejar las peticiones relacionadas con la agenda. # Permite obtener y mostrar las actividades programadas para el día. import datetime import logging -from google_calendar import get_events +from talia_bot.modules.calendar import get_events logger = logging.getLogger(__name__) diff --git a/app/modules/aprobaciones.py b/talia_bot/modules/aprobaciones.py similarity index 100% rename from app/modules/aprobaciones.py rename to talia_bot/modules/aprobaciones.py diff --git a/app/google_calendar.py b/talia_bot/modules/calendar.py similarity index 100% rename from app/google_calendar.py rename to talia_bot/modules/calendar.py diff --git a/app/modules/citas.py b/talia_bot/modules/citas.py similarity index 100% rename from app/modules/citas.py rename to talia_bot/modules/citas.py diff --git a/app/modules/create_tag.py b/talia_bot/modules/create_tag.py similarity index 100% rename from app/modules/create_tag.py rename to talia_bot/modules/create_tag.py diff --git a/app/modules/print.py b/talia_bot/modules/debug.py similarity index 88% rename from app/modules/print.py rename to talia_bot/modules/debug.py index f0495bf..c83bd69 100644 --- a/app/modules/print.py +++ b/talia_bot/modules/debug.py @@ -1,11 +1,11 @@ -# app/modules/print.py +# talia_bot/modules/debug.py # Este módulo permite a los administradores imprimir los detalles de configuración del bot. # Es una herramienta útil para depuración (debugging). from telegram import Update from telegram.ext import ContextTypes -from permissions import is_admin -from config import TIMEZONE, CALENDAR_ID, N8N_WEBHOOK_URL +from talia_bot.modules.identity import is_admin +from talia_bot.config import TIMEZONE, CALENDAR_ID, N8N_WEBHOOK_URL async def print_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """ diff --git a/app/modules/equipo.py b/talia_bot/modules/equipo.py similarity index 100% rename from app/modules/equipo.py rename to talia_bot/modules/equipo.py diff --git a/talia_bot/modules/identity.py b/talia_bot/modules/identity.py new file mode 100644 index 0000000..c169c32 --- /dev/null +++ b/talia_bot/modules/identity.py @@ -0,0 +1,71 @@ +# talia_bot/modules/identity.py +# Este script maneja los roles y permisos de los usuarios. + +import logging +from talia_bot.db import get_db_connection +from talia_bot.config import ADMIN_ID + +logger = logging.getLogger(__name__) + +def add_user(telegram_id, role, name=None, employee_id=None, branch=None): + """ + Añade un nuevo usuario o actualiza el rol de uno existente. + """ + try: + conn = get_db_connection() + cursor = conn.cursor() + cursor.execute(""" + INSERT INTO users (telegram_id, role, name, employee_id, branch) + VALUES (?, ?, ?, ?, ?) + ON CONFLICT(telegram_id) DO UPDATE SET + role = excluded.role, + name = excluded.name, + employee_id = excluded.employee_id, + branch = excluded.branch + """, (telegram_id, role, name, employee_id, branch)) + conn.commit() + logger.info(f"Usuario {telegram_id} añadido/actualizado con el rol {role}.") + return True + except Exception as e: + logger.error(f"Error al añadir/actualizar usuario {telegram_id}: {e}") + return False + finally: + if conn: + conn.close() + +def get_user_role(telegram_id): + """ + Determina el rol de un usuario. + Roles: 'admin', 'crew', 'client'. + """ + # El admin principal se define en el .env para el primer arranque + if str(telegram_id) == ADMIN_ID: + return 'admin' + + try: + conn = get_db_connection() + cursor = conn.cursor() + cursor.execute("SELECT role FROM users WHERE telegram_id = ?", (telegram_id,)) + user = cursor.fetchone() + + if user: + logger.debug(f"Rol encontrado para {telegram_id}: {user['role']}") + return user['role'] + else: + # Si no está en la DB, es un cliente nuevo + logger.debug(f"No se encontró rol para {telegram_id}, asignando 'client'.") + return 'client' + except Exception as e: + logger.error(f"Error al obtener el rol para {telegram_id}: {e}") + return 'client' # Fallback seguro + finally: + if conn: + conn.close() + +def is_admin(telegram_id): + """Verifica si un usuario es administrador.""" + return get_user_role(telegram_id) == 'admin' + +def is_crew(telegram_id): + """Verifica si un usuario es del equipo (crew) o administrador.""" + return get_user_role(telegram_id) in ['admin', 'crew'] diff --git a/app/llm.py b/talia_bot/modules/llm_engine.py similarity index 92% rename from app/llm.py rename to talia_bot/modules/llm_engine.py index a67b178..c146d2b 100644 --- a/app/llm.py +++ b/talia_bot/modules/llm_engine.py @@ -1,8 +1,8 @@ -# app/llm.py +# talia_bot/modules/llm_engine.py # Este script se encarga de la comunicación con la inteligencia artificial de OpenAI. import openai -from config import OPENAI_API_KEY, OPENAI_MODEL +from talia_bot.config import OPENAI_API_KEY, OPENAI_MODEL def get_smart_response(prompt): """ diff --git a/app/modules/onboarding.py b/talia_bot/modules/onboarding.py similarity index 75% rename from app/modules/onboarding.py rename to talia_bot/modules/onboarding.py index 567e7d8..795b5b7 100644 --- a/app/modules/onboarding.py +++ b/talia_bot/modules/onboarding.py @@ -1,23 +1,15 @@ -# app/modules/onboarding.py +# talia_bot/modules/onboarding.py # 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 (dueño, admin, equipo o cliente). +# Se encarga de mostrar un menú diferente según quién sea el usuario (admin, crew o cliente). from telegram import InlineKeyboardButton, InlineKeyboardMarkup -def get_owner_menu(): - """Crea el menú de botones para el Dueño (Owner).""" - keyboard = [ - [InlineKeyboardButton("📅 Ver mi agenda", callback_data='view_agenda')], - [InlineKeyboardButton("⏳ Ver pendientes", callback_data='view_pending')], - ] - return InlineKeyboardMarkup(keyboard) - def get_admin_menu(): """Crea el menú de botones principal para los Administradores.""" keyboard = [ - [InlineKeyboardButton("⏳ Revisar Pendientes", callback_data='view_pending')], + [InlineKeyboardButton("👑 Revisar Pendientes", callback_data='view_pending')], [InlineKeyboardButton("📅 Agenda", callback_data='view_agenda')], - [InlineKeyboardButton("🏷️ Crear Tag", callback_data='start_create_tag')], + [InlineKeyboardButton(" NFC", callback_data='start_create_tag')], [InlineKeyboardButton("▶️ Más opciones", callback_data='admin_menu')], ] return InlineKeyboardMarkup(keyboard) @@ -33,7 +25,7 @@ def get_admin_secondary_menu(): reply_markup = InlineKeyboardMarkup(keyboard) return text, reply_markup -def get_team_menu(): +def get_crew_menu(): """Crea el menú de botones para los Miembros del Equipo.""" keyboard = [ [InlineKeyboardButton("🕒 Proponer actividad", callback_data='propose_activity')], @@ -55,10 +47,10 @@ def handle_start(user_role): """ welcome_message = "Hola, soy Talía. ¿En qué puedo ayudarte hoy?" - if user_role in ["owner", "admin"]: + if user_role == "admin": menu = get_admin_menu() - elif user_role == "team": - menu = get_team_menu() + elif user_role == "crew": + menu = get_crew_menu() else: menu = get_client_menu() diff --git a/talia_bot/modules/printer.py b/talia_bot/modules/printer.py new file mode 100644 index 0000000..698f9c0 --- /dev/null +++ b/talia_bot/modules/printer.py @@ -0,0 +1 @@ +# This module will contain the SMTP/IMAP loop for the remote printing service. diff --git a/talia_bot/modules/sales_rag.py b/talia_bot/modules/sales_rag.py new file mode 100644 index 0000000..1f31fb9 --- /dev/null +++ b/talia_bot/modules/sales_rag.py @@ -0,0 +1 @@ +# This module will contain the sales RAG flow for new clients. diff --git a/app/modules/servicios.py b/talia_bot/modules/servicios.py similarity index 100% rename from app/modules/servicios.py rename to talia_bot/modules/servicios.py diff --git a/app/modules/vikunja.py b/talia_bot/modules/vikunja.py similarity index 100% rename from app/modules/vikunja.py rename to talia_bot/modules/vikunja.py diff --git a/app/scheduler.py b/talia_bot/scheduler.py similarity index 100% rename from app/scheduler.py rename to talia_bot/scheduler.py diff --git a/app/webhook_client.py b/talia_bot/webhook_client.py similarity index 100% rename from app/webhook_client.py rename to talia_bot/webhook_client.py diff --git a/test_calendar_debug.py b/test_calendar_debug.py index aa27442..501eee8 100644 --- a/test_calendar_debug.py +++ b/test_calendar_debug.py @@ -3,9 +3,9 @@ import sys import os # Add app directory to path -sys.path.append(os.path.join(os.getcwd(), 'app')) +sys.path.append(os.path.join(os.getcwd(), 'talia_bot')) -from google_calendar import get_events +from modules.calendar import get_events from config import CALENDAR_ID def test_get_events():