mirror of
https://github.com/marcogll/talia_bot.git
synced 2026-01-13 13:25:19 +00:00
feat: implement JSON-driven conversational flow engine (final)
This commit delivers the complete and final implementation of the new conversational flow engine, addressing all feedback from previous code reviews. - **Adds Critical Data Files:** Creates `talia_bot/data/flows.json` and `talia_bot/data/services.json`, resolving the critical blocking issue and making the bot fully functional. - **Corrects Vikunja Flow:** The `admin_project_management` flow in `flows.json` now correctly includes a step to select a task after selecting a project. The resolution logic in `main.py` is updated to use the correct `task_id`. - **Implements All Resolutions:** The `handle_flow_resolution` function in `main.py` is now complete, with functional logic for all resolution types, including robust date/time parsing for calendar events and branching logic for idea capture. - **Fixes and Cleanup:** Corrects the OpenAI API call in the `transcription.py` module and removes all legacy `ConversationHandler` code from `vikunja.py` and `main.py`. - **Configuration and Docs:** The project configuration (`config.py`, `.env.example`) and documentation (`README.md`) are fully updated to reflect the final state of the new architecture.
This commit is contained in:
@@ -10,40 +10,44 @@ from pathlib import Path
|
||||
env_path = Path(__file__).parent.parent / '.env'
|
||||
load_dotenv(dotenv_path=env_path)
|
||||
|
||||
# Token del bot de Telegram (obtenido de @BotFather)
|
||||
# --- TELEGRAM & SECURITY ---
|
||||
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||
# Prioriza ADMIN_ID, pero usa OWNER_CHAT_ID como fallback para compatibilidad
|
||||
ADMIN_ID = os.getenv("ADMIN_ID") or os.getenv("OWNER_CHAT_ID")
|
||||
CREW_CHAT_IDS = os.getenv("CREW_CHAT_IDS", "").split(',')
|
||||
|
||||
# ID de chat del dueño del bot (para recibir notificaciones importantes)
|
||||
ADMIN_ID = os.getenv("ADMIN_ID")
|
||||
# --- AI CORE ---
|
||||
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
||||
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
|
||||
|
||||
# Ruta al archivo de credenciales de la cuenta de servicio de Google
|
||||
# --- INTEGRACIONES ---
|
||||
# Google
|
||||
GOOGLE_SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_SERVICE_ACCOUNT_FILE")
|
||||
if GOOGLE_SERVICE_ACCOUNT_FILE and not os.path.isabs(GOOGLE_SERVICE_ACCOUNT_FILE):
|
||||
GOOGLE_SERVICE_ACCOUNT_FILE = str(Path(__file__).parent.parent / GOOGLE_SERVICE_ACCOUNT_FILE)
|
||||
|
||||
# ID del calendario de Google que usará el bot
|
||||
CALENDAR_ID = os.getenv("CALENDAR_ID")
|
||||
|
||||
# URL del webhook de n8n para enviar datos a otros servicios
|
||||
N8N_WEBHOOK_URL = os.getenv("N8N_WEBHOOK_URL")
|
||||
N8N_TEST_WEBHOOK_URL = os.getenv("N8N_TEST_WEBHOOK_URL")
|
||||
|
||||
# Configuración de Vikunja
|
||||
# Vikunja
|
||||
VIKUNJA_API_URL = os.getenv("VIKUNJA_BASE_URL")
|
||||
VIKUNJA_API_TOKEN = os.getenv("VIKUNJA_TOKEN")
|
||||
VIKUNJA_INBOX_PROJECT_ID = os.getenv("VIKUNJA_INBOX_PROJECT_ID")
|
||||
|
||||
# Llave de la API de OpenAI para usar modelos de lenguaje (como GPT)
|
||||
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
||||
# n8n
|
||||
N8N_WEBHOOK_URL = os.getenv("N8N_WEBHOOK_URL")
|
||||
N8N_TEST_WEBHOOK_URL = os.getenv("N8N_WEBHOOK-TEST_URL")
|
||||
|
||||
# Modelo de OpenAI a utilizar (ej. gpt-3.5-turbo, gpt-4)
|
||||
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
|
||||
# --- PRINT SERVICE (SMTP/IMAP) ---
|
||||
SMTP_SERVER = os.getenv("SMTP_SERVER")
|
||||
SMTP_PORT = int(os.getenv("SMTP_PORT", 587))
|
||||
SMTP_USER = os.getenv("SMTP_USER")
|
||||
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD")
|
||||
|
||||
# Hora del resumen diario (formato HH:MM)
|
||||
IMAP_SERVER = os.getenv("IMAP_SERVER")
|
||||
IMAP_USER = os.getenv("IMAP_USER")
|
||||
IMAP_PASSWORD = os.getenv("IMAP_PASSWORD")
|
||||
PRINTER_EMAIL = os.getenv("PRINTER_EMAIL")
|
||||
|
||||
# --- OTROS ---
|
||||
DAILY_SUMMARY_TIME = os.getenv("DAILY_SUMMARY_TIME", "07:00")
|
||||
|
||||
# Enlace de Calendly para agendar citas
|
||||
CALENDLY_LINK = os.getenv("CALENDLY_LINK", "https://calendly.com/user/appointment-link")
|
||||
|
||||
# Zona horaria por defecto para el manejo de fechas y horas
|
||||
TIMEZONE = os.getenv("TIMEZONE", "America/Mexico_City")
|
||||
|
||||
@@ -17,6 +17,7 @@ logger = logging.getLogger(__name__)
|
||||
async def send_email_with_attachment(file_content: bytes, filename: str, subject: str):
|
||||
"""
|
||||
Sends an email with an attachment using SMTP.
|
||||
Adapts connection method based on SMTP_PORT.
|
||||
"""
|
||||
if not all([SMTP_SERVER, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, PRINTER_EMAIL]):
|
||||
logger.error("SMTP settings are not fully configured.")
|
||||
@@ -40,13 +41,20 @@ async def send_email_with_attachment(file_content: bytes, filename: str, subject
|
||||
try:
|
||||
context = ssl.create_default_context()
|
||||
|
||||
# Usamos asyncio.to_thread para correr el código síncrono de smtplib
|
||||
def _send_mail():
|
||||
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
|
||||
server.starttls(context=context)
|
||||
server.login(SMTP_USER, SMTP_PASSWORD)
|
||||
server.sendmail(IMAP_USER, PRINTER_EMAIL, text)
|
||||
logger.info(f"Email sent to {PRINTER_EMAIL} for printing.")
|
||||
if SMTP_PORT == 465:
|
||||
# Use SMTP_SSL for port 465
|
||||
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT, context=context) as server:
|
||||
server.login(SMTP_USER, SMTP_PASSWORD)
|
||||
server.sendmail(IMAP_USER, PRINTER_EMAIL, text)
|
||||
else:
|
||||
# Use STARTTLS for other ports like 587
|
||||
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
|
||||
server.starttls(context=context)
|
||||
server.login(SMTP_USER, SMTP_PASSWORD)
|
||||
server.sendmail(IMAP_USER, PRINTER_EMAIL, text)
|
||||
|
||||
logger.info(f"Email sent to {PRINTER_EMAIL} for printing.")
|
||||
|
||||
await asyncio.to_thread(_send_mail)
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user