mirror of
https://github.com/marcogll/talia_bot.git
synced 2026-01-13 21:35:19 +00:00
Merge pull request #19 from marcogll/feat/project-restructure-12016173615219522068
Refactor: Restructure Project and Implement DB-based Roles
This commit is contained in:
26
.env.example
26
.env.example
@@ -1,12 +1,18 @@
|
|||||||
|
# --- TELEGRAM & SECURITY ---
|
||||||
TELEGRAM_BOT_TOKEN=
|
TELEGRAM_BOT_TOKEN=
|
||||||
OWNER_CHAT_ID=
|
ADMIN_ID=
|
||||||
ADMIN_CHAT_IDS=
|
|
||||||
TEAM_CHAT_IDS=
|
# --- AI CORE ---
|
||||||
GOOGLE_SERVICE_ACCOUNT_FILE=
|
|
||||||
CALENDAR_ID=
|
|
||||||
N8N_WEBHOOK_URL=
|
|
||||||
OPENAI_API_KEY=
|
OPENAI_API_KEY=
|
||||||
OPENAI_MODEL=gpt-3.5-turbo
|
|
||||||
DAILY_SUMMARY_TIME=07:00
|
# --- INTEGRATIONS ---
|
||||||
CALENDLY_LINK=https://calendly.com/user/appointment-link
|
VIKUNJA_API_URL=https://tuservidor.com/api/v1
|
||||||
TIMEZONE=America/Mexico_City
|
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
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
FROM python:3.9-slim
|
FROM python:3.9-slim
|
||||||
|
|
||||||
# Set working directory
|
# Set working directory
|
||||||
WORKDIR /app
|
WORKDIR /talia_bot
|
||||||
|
|
||||||
# Copy and install requirements
|
# Copy and install requirements
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
# Copy app code
|
# Copy app code
|
||||||
COPY app/ .
|
COPY talia_bot/ .
|
||||||
|
|
||||||
# Run the bot
|
# Run the bot
|
||||||
CMD ["python", "main.py"]
|
CMD ["python", "main.py"]
|
||||||
|
|||||||
338
README.md
338
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.
|
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.
|
||||||
|
|
||||||
Talía no improvisa ni asume. **Consulta, valida, confirma y ejecuta.**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 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
|
| Rol | Icono | Descripción | Permisos |
|
||||||
* Validar disponibilidad real antes de comprometer tiempo
|
| :------ | :---: | :------------------ | :-------------------------------------------------------------------------------- |
|
||||||
* Priorizar clientes sin romper compromisos existentes
|
| **Admin** | 👑 | Dueño / Gerente | God Mode: Gestión total de proyectos, bloqueos de calendario, generación de identidad NFC e impresión. |
|
||||||
* Delegar reglas de negocio y disponibilidad a flujos en n8n
|
| **Crew** | 👷 | Equipo Operativo | Limitado: Solicitud de agenda (validada), asignación de tareas, impresión de documentos. |
|
||||||
* Mantener trazabilidad completa mediante eventos webhook
|
| **Cliente** | 👤 | Usuario Público | Ventas: Embudo de captación, consulta de servicios (RAG) y agendamiento comercial. |
|
||||||
* Escalar de forma modular sin romper flujos existentes
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🧠 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
|
1. **Input**: Telegram (Texto o Audio).
|
||||||
* Proactiva, pero nunca invasiva
|
2. **STT**: Whisper (Conversión de Audio a Texto).
|
||||||
* Siempre confirma antes de agendar o ejecutar acciones
|
3. **Router**: Verificación de ID contra la base de datos de usuarios.
|
||||||
* No improvisa horarios ni decisiones
|
4. **Cerebro (LLM)**: OpenAI (Fase 1) / Google Gemini (Fase 2).
|
||||||
* Comunica decisiones con calma, orden y neutralidad
|
5. **Tools**:
|
||||||
|
* **Vikunja API**: Lectura/Escritura de tareas con filtrado de privacidad.
|
||||||
Talía no es informal, no es robótica y no utiliza sarcasmo. Su función es **ordenar el día, no interrumpirlo**.
|
* **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
|
* **Proyectos (Vikunja)**:
|
||||||
* Recibe resumen diario automático a las 7:00 AM
|
* Resumen inteligente de estatus de proyectos.
|
||||||
* Aprueba o rechaza solicitudes del equipo
|
* Comandos naturales: *"Marca el proyecto de web como terminado y comenta que se envió factura"*.
|
||||||
* Puede interactuar desde su número privado
|
* **Wizard de Identidad (NFC)**:
|
||||||
* Tiene prioridad absoluta sobre cualquier decisión
|
* 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)
|
* **Solicitud de Tiempo (Wizard)**:
|
||||||
* Visualizan únicamente horarios disponibles
|
* Solicita espacios de 1 a 4 horas.
|
||||||
* No tienen acceso a la agenda completa
|
* **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)
|
* Permite enviar archivos desde Telegram a la impresora física de la oficina.
|
||||||
* Puede solicitar acciones operativas
|
* **Envío (SMTP)**: El bot envía el documento a un correo designado.
|
||||||
* Toda actividad que consuma tiempo requiere aprobación
|
* **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
|
* Identifica usuarios nuevos (no registrados en la DB).
|
||||||
* Requieren validación adicional
|
* Captura datos (Lead Magnet).
|
||||||
* Acceden a flujos administrativos restringidos
|
* 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
|
* Python 3.10+
|
||||||
2. **Cerebro Central** – Python
|
* Cuenta de Telegram Bot (@BotFather)
|
||||||
3. **Automatización y Reglas** – n8n
|
* Instancia de Vikunja (Self-hosted)
|
||||||
4. **Servicios Externos** – Google Calendar, IA, APIs
|
* 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
|
||||||
|
|
||||||
---
|
```bash
|
||||||
|
git clone https://github.com/marcogll/talia_bot_mg.git
|
||||||
## 📁 Estructura del Proyecto
|
cd talia_bot_mg
|
||||||
|
python -m venv venv
|
||||||
```text
|
source venv/bin/activate # Windows: venv\Scripts\activate
|
||||||
talia-bot/
|
pip install -r requirements.txt
|
||||||
├── 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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
### 2. Variables de Entorno (`.env`)
|
||||||
|
|
||||||
## 🧠 Cerebro del Sistema (`main.py`)
|
Crea un archivo `.env` en la raíz con la siguiente estructura:
|
||||||
|
|
||||||
`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
|
|
||||||
|
|
||||||
```env
|
```env
|
||||||
TELEGRAM_BOT_TOKEN=
|
# --- TELEGRAM & SECURITY ---
|
||||||
OWNER_CHAT_ID=
|
TELEGRAM_BOT_TOKEN=tu_token_telegram
|
||||||
ADMIN_CHAT_IDS=
|
ADMIN_ID=tu_telegram_id
|
||||||
TEAM_CHAT_IDS=
|
|
||||||
GOOGLE_CLIENT_ID=
|
# --- AI CORE ---
|
||||||
GOOGLE_CLIENT_SECRET=
|
OPENAI_API_KEY=sk-...
|
||||||
GOOGLE_REFRESH_TOKEN=
|
|
||||||
N8N_WEBHOOK_URL=
|
# --- INTEGRACIONES ---
|
||||||
OPENAI_API_KEY=
|
VIKUNJA_API_URL=https://tuservidor.com/api/v1
|
||||||
TIMEZONE=America/Mexico_City
|
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
|
- [ ] Implementar Wizard de creación de Tags NFC (Base64).
|
||||||
version: "3.9"
|
- [ ] Conectar Loop de Impresión (SMTP/IMAP).
|
||||||
services:
|
- [ ] Migrar de OpenAI a Google Gemini 1.5 Pro.
|
||||||
talia-bot:
|
- [ ] Implementar soporte para fotos en impresión.
|
||||||
build: .
|
|
||||||
container_name: talia-bot
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
restart: unless-stopped
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Guía de Desarrollo
|
Desarrollado por: Marco G.
|
||||||
|
Asistente Personalizado v1.0
|
||||||
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.
|
|
||||||
|
|||||||
@@ -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"]
|
|
||||||
@@ -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.
|
# 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).
|
# 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")
|
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||||
|
|
||||||
# ID de chat del dueño del bot (para recibir notificaciones importantes)
|
# ID de chat del dueño del bot (para recibir notificaciones importantes)
|
||||||
OWNER_CHAT_ID = os.getenv("OWNER_CHAT_ID")
|
ADMIN_ID = os.getenv("ADMIN_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(",")
|
|
||||||
|
|
||||||
# Ruta al archivo de credenciales de la cuenta de servicio de Google
|
# Ruta al archivo de credenciales de la cuenta de servicio de Google
|
||||||
GOOGLE_SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_SERVICE_ACCOUNT_FILE")
|
GOOGLE_SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_SERVICE_ACCOUNT_FILE")
|
||||||
BIN
talia_bot/data/users.db
Normal file
BIN
talia_bot/data/users.db
Normal file
Binary file not shown.
48
talia_bot/db.py
Normal file
48
talia_bot/db.py
Normal file
@@ -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.")
|
||||||
@@ -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.
|
# Este es el archivo principal del bot. Aquí se inicia todo y se configuran los comandos.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@@ -15,13 +15,13 @@ 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 talia_bot.config import TELEGRAM_BOT_TOKEN
|
||||||
from permissions import get_user_role
|
from talia_bot.modules.identity import get_user_role
|
||||||
from modules.onboarding import handle_start as onboarding_handle_start
|
from talia_bot.modules.onboarding import handle_start as onboarding_handle_start
|
||||||
from modules.onboarding import get_admin_secondary_menu
|
from talia_bot.modules.onboarding import get_admin_secondary_menu
|
||||||
from modules.agenda import get_agenda
|
from talia_bot.modules.agenda import get_agenda
|
||||||
from modules.citas import request_appointment
|
from talia_bot.modules.citas import request_appointment
|
||||||
from modules.equipo import (
|
from talia_bot.modules.equipo import (
|
||||||
propose_activity_start,
|
propose_activity_start,
|
||||||
get_description,
|
get_description,
|
||||||
get_duration,
|
get_duration,
|
||||||
@@ -30,14 +30,15 @@ from modules.equipo import (
|
|||||||
DESCRIPTION,
|
DESCRIPTION,
|
||||||
DURATION,
|
DURATION,
|
||||||
)
|
)
|
||||||
from modules.aprobaciones import view_pending, handle_approval_action
|
from talia_bot.modules.aprobaciones import view_pending, handle_approval_action
|
||||||
from modules.servicios import get_service_info
|
from talia_bot.modules.servicios import get_service_info
|
||||||
from modules.admin import get_system_status
|
from talia_bot.modules.admin import get_system_status
|
||||||
from modules.print import print_handler
|
from talia_bot.modules.debug import print_handler
|
||||||
from modules.create_tag import create_tag_conv_handler
|
from talia_bot.modules.create_tag import create_tag_conv_handler
|
||||||
from modules.vikunja import vikunja_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
|
# Configuramos el sistema de logs para ver mensajes de estado en la consola
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@@ -124,6 +125,8 @@ def main() -> None:
|
|||||||
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
|
||||||
|
|
||||||
|
setup_database()
|
||||||
|
|
||||||
application = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
|
application = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
|
||||||
schedule_daily_summary(application)
|
schedule_daily_summary(application)
|
||||||
|
|
||||||
@@ -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.
|
# 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 google_calendar import get_events
|
from talia_bot.modules.calendar import get_events
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -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.
|
# 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 permissions import is_admin
|
from talia_bot.modules.identity import is_admin
|
||||||
from config import TIMEZONE, CALENDAR_ID, N8N_WEBHOOK_URL
|
from talia_bot.config import TIMEZONE, 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:
|
||||||
"""
|
"""
|
||||||
71
talia_bot/modules/identity.py
Normal file
71
talia_bot/modules/identity.py
Normal file
@@ -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']
|
||||||
@@ -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.
|
# Este script se encarga de la comunicación con la inteligencia artificial de OpenAI.
|
||||||
|
|
||||||
import 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):
|
def get_smart_response(prompt):
|
||||||
"""
|
"""
|
||||||
@@ -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).
|
# 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
|
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():
|
def get_admin_menu():
|
||||||
"""Crea el menú de botones principal para los Administradores."""
|
"""Crea el menú de botones principal para los Administradores."""
|
||||||
keyboard = [
|
keyboard = [
|
||||||
[InlineKeyboardButton("⏳ Revisar Pendientes", callback_data='view_pending')],
|
[InlineKeyboardButton("👑 Revisar Pendientes", callback_data='view_pending')],
|
||||||
[InlineKeyboardButton("📅 Agenda", callback_data='view_agenda')],
|
[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')],
|
[InlineKeyboardButton("▶️ Más opciones", callback_data='admin_menu')],
|
||||||
]
|
]
|
||||||
return InlineKeyboardMarkup(keyboard)
|
return InlineKeyboardMarkup(keyboard)
|
||||||
@@ -33,7 +25,7 @@ def get_admin_secondary_menu():
|
|||||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
return text, reply_markup
|
return text, reply_markup
|
||||||
|
|
||||||
def get_team_menu():
|
def get_crew_menu():
|
||||||
"""Crea el menú de botones para los Miembros del Equipo."""
|
"""Crea el menú de botones para los Miembros del Equipo."""
|
||||||
keyboard = [
|
keyboard = [
|
||||||
[InlineKeyboardButton("🕒 Proponer actividad", callback_data='propose_activity')],
|
[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?"
|
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()
|
menu = get_admin_menu()
|
||||||
elif user_role == "team":
|
elif user_role == "crew":
|
||||||
menu = get_team_menu()
|
menu = get_crew_menu()
|
||||||
else:
|
else:
|
||||||
menu = get_client_menu()
|
menu = get_client_menu()
|
||||||
|
|
||||||
1
talia_bot/modules/printer.py
Normal file
1
talia_bot/modules/printer.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# This module will contain the SMTP/IMAP loop for the remote printing service.
|
||||||
1
talia_bot/modules/sales_rag.py
Normal file
1
talia_bot/modules/sales_rag.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# This module will contain the sales RAG flow for new clients.
|
||||||
@@ -3,9 +3,9 @@ import sys
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
# Add app directory to path
|
# 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
|
from config import CALENDAR_ID
|
||||||
|
|
||||||
def test_get_events():
|
def test_get_events():
|
||||||
|
|||||||
Reference in New Issue
Block a user