mirror of
https://github.com/marcogll/telegram_new_socias.git
synced 2026-01-13 13:15:16 +00:00
feat: Add database health checks and host configuration, enhance the start command with a quick reply keyboard, and improve general text cleaning.
This commit is contained in:
@@ -6,11 +6,12 @@ GOOGLE_API_KEY=AIzaSyBqH5...
|
|||||||
|
|
||||||
|
|
||||||
# Webhooks de n8n (puedes agregar más aquí en el futuro)
|
# Webhooks de n8n (puedes agregar más aquí en el futuro)
|
||||||
WEBHOOK_CONTRATO=url
|
# Usa WEBHOOK_ONBOARDING (o el alias WEBHOOK_CONTRATO si ya lo tienes así)
|
||||||
|
WEBHOOK_ONBOARDING=url
|
||||||
|
# WEBHOOK_CONTRATO=url
|
||||||
WEBHOOK_PRINT=url
|
WEBHOOK_PRINT=url
|
||||||
WEBHOOK_VACACIONES=url
|
WEBHOOK_VACACIONES=url
|
||||||
WEBHOOK_PERMISOS=url
|
WEBHOOK_PERMISOS=url
|
||||||
WEBHOOK_DATA_EMPLEADO=url
|
|
||||||
|
|
||||||
# --- DATABASE ---
|
# --- DATABASE ---
|
||||||
# Usado por el servicio de la base de datos en docker-compose.yml
|
# Usado por el servicio de la base de datos en docker-compose.yml
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ Copia el archivo `.env.example` a `.env` y rellena los valores correspondientes.
|
|||||||
TELEGRAM_TOKEN=TU_TOKEN_AQUI
|
TELEGRAM_TOKEN=TU_TOKEN_AQUI
|
||||||
|
|
||||||
# --- WEBHOOKS N8N ---
|
# --- WEBHOOKS N8N ---
|
||||||
WEBHOOK_CONTRATO=https://... # También acepta WEBHOOK_ONBOARDING
|
WEBHOOK_ONBOARDING=https://... # Alias aceptado: WEBHOOK_CONTRATO
|
||||||
WEBHOOK_PRINT=https://...
|
WEBHOOK_PRINT=https://...
|
||||||
WEBHOOK_VACACIONES=https://...
|
WEBHOOK_VACACIONES=https://...
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
- MYSQL_HOST=db
|
||||||
- MYSQL_USER=${MYSQL_USER}
|
- MYSQL_USER=${MYSQL_USER}
|
||||||
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
|
||||||
- MYSQL_DATABASE=${MYSQL_DATABASE}
|
- MYSQL_DATABASE=${MYSQL_DATABASE}
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
db:
|
||||||
|
condition: service_healthy
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
|
|
||||||
@@ -25,6 +27,12 @@ services:
|
|||||||
MYSQL_USER: ${MYSQL_USER}
|
MYSQL_USER: ${MYSQL_USER}
|
||||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "mysqladmin ping -h localhost -u${MYSQL_USER} -p${MYSQL_PASSWORD}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 6
|
||||||
|
start_period: 30s
|
||||||
volumes:
|
volumes:
|
||||||
- mysql_data:/var/lib/mysql
|
- mysql_data:/var/lib/mysql
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
14
main.py
14
main.py
@@ -5,7 +5,7 @@ from dotenv import load_dotenv
|
|||||||
# Cargar variables de entorno antes de importar módulos que las usan
|
# Cargar variables de entorno antes de importar módulos que las usan
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
from telegram import Update
|
from telegram import Update, ReplyKeyboardMarkup
|
||||||
from telegram.constants import ParseMode
|
from telegram.constants import ParseMode
|
||||||
from telegram.ext import Application, Defaults, CommandHandler, ContextTypes
|
from telegram.ext import Application, Defaults, CommandHandler, ContextTypes
|
||||||
|
|
||||||
@@ -27,13 +27,13 @@ async def menu_principal(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
log_request(user.id, user.username, "start", update.message.text)
|
log_request(user.id, user.username, "start", update.message.text)
|
||||||
texto = (
|
texto = (
|
||||||
"👩💼 **Hola, soy Vanessa. ¿En qué puedo ayudarte hoy?**\n\n"
|
"👩💼 **Hola, soy Vanessa. ¿En qué puedo ayudarte hoy?**\n\n"
|
||||||
"📝 `/welcome` - Iniciar onboarding/contrato\n"
|
"Toca un comando en azul para lanzarlo rápido:"
|
||||||
"🖨️ `/print` - Imprimir o enviar archivo\n"
|
|
||||||
"🌴 `/vacaciones` - Solicitar días libres\n"
|
|
||||||
"⏱️ `/permiso` - Solicitar permiso por horas\n\n"
|
|
||||||
"Selecciona un comando para empezar."
|
|
||||||
)
|
)
|
||||||
await update.message.reply_text(texto)
|
teclado = ReplyKeyboardMarkup(
|
||||||
|
[["/welcome", "/print"], ["/vacaciones", "/permiso"]],
|
||||||
|
resize_keyboard=True
|
||||||
|
)
|
||||||
|
await update.message.reply_text(texto, reply_markup=teclado)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Configuración Global
|
# Configuración Global
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ def _build_engine():
|
|||||||
logging.error(f"No se pudo crear el engine de base de datos: {exc}")
|
logging.error(f"No se pudo crear el engine de base de datos: {exc}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _disable_db_logging(reason: str):
|
||||||
|
"""Deshabilita el logging a DB después de un error para evitar spam."""
|
||||||
|
global engine, SessionLocal
|
||||||
|
engine = None
|
||||||
|
SessionLocal = None
|
||||||
|
logging.warning(f"DB logging deshabilitado: {reason}")
|
||||||
|
|
||||||
# Crear el engine y sesión si es posible
|
# Crear el engine y sesión si es posible
|
||||||
engine = _build_engine()
|
engine = _build_engine()
|
||||||
metadata = MetaData() if engine else None
|
metadata = MetaData() if engine else None
|
||||||
@@ -46,6 +53,7 @@ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) if e
|
|||||||
|
|
||||||
# Función para inicializar la base de datos
|
# Función para inicializar la base de datos
|
||||||
def init_db():
|
def init_db():
|
||||||
|
global engine, SessionLocal
|
||||||
if not engine:
|
if not engine:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@@ -54,6 +62,7 @@ def init_db():
|
|||||||
logging.info("Tablas verificadas/creadas correctamente.")
|
logging.info("Tablas verificadas/creadas correctamente.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error al inicializar la base de datos: {e}")
|
logging.error(f"Error al inicializar la base de datos: {e}")
|
||||||
|
_disable_db_logging("no se pudo inicializar la base de datos (se omitirán logs).")
|
||||||
# No propagamos para que el bot pueda seguir levantando aunque no haya DB
|
# No propagamos para que el bot pueda seguir levantando aunque no haya DB
|
||||||
|
|
||||||
# Función para registrar una solicitud en la base de datos
|
# Función para registrar una solicitud en la base de datos
|
||||||
@@ -62,7 +71,12 @@ def log_request(telegram_id, username, command, message):
|
|||||||
logging.debug("Log de DB omitido (DB no configurada).")
|
logging.debug("Log de DB omitido (DB no configurada).")
|
||||||
return
|
return
|
||||||
|
|
||||||
db_session = SessionLocal()
|
try:
|
||||||
|
db_session = SessionLocal()
|
||||||
|
except Exception as exc:
|
||||||
|
logging.error(f"No se pudo crear sesión DB, se deshabilita el log: {exc}")
|
||||||
|
_disable_db_logging("no se pudo abrir sesión")
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
log_entry = RequestLog(
|
log_entry = RequestLog(
|
||||||
telegram_id=str(telegram_id),
|
telegram_id=str(telegram_id),
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ logging.basicConfig(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Convertimos la string del webhook en una lista (por si en el futuro hay varios separados por coma)
|
# Convertimos la string del webhook en una lista (por si en el futuro hay varios separados por coma)
|
||||||
# Se aceptan los nombres WEBHOOK_CONTRATO (nuevo) y WEBHOOK_ONBOARDING (legacy).
|
# Se aceptan los nombres WEBHOOK_ONBOARDING (principal) y WEBHOOK_CONTRATO (alias).
|
||||||
_webhook_raw = os.getenv("WEBHOOK_CONTRATO") or os.getenv("WEBHOOK_ONBOARDING") or ""
|
_webhook_raw = os.getenv("WEBHOOK_ONBOARDING") or os.getenv("WEBHOOK_CONTRATO") or ""
|
||||||
WEBHOOK_URLS = [w.strip() for w in _webhook_raw.split(",") if w.strip()]
|
WEBHOOK_URLS = [w.strip() for w in _webhook_raw.split(",") if w.strip()]
|
||||||
|
|
||||||
if not WEBHOOK_URLS:
|
if not WEBHOOK_URLS:
|
||||||
logging.warning("No se configuró WEBHOOK_CONTRATO/WEBHOOK_ONBOARDING; el onboarding no enviará datos.")
|
logging.warning("No se configuró WEBHOOK_ONBOARDING (o alias WEBHOOK_CONTRATO); el onboarding no enviará datos.")
|
||||||
|
|
||||||
# --- 2. ESTADOS DEL FLUJO ---
|
# --- 2. ESTADOS DEL FLUJO ---
|
||||||
(
|
(
|
||||||
@@ -63,7 +63,8 @@ def normalizar_id(texto: str) -> str:
|
|||||||
return "N/A" if limpio == "0" else limpio
|
return "N/A" if limpio == "0" else limpio
|
||||||
|
|
||||||
def limpiar_texto_general(texto: str) -> str:
|
def limpiar_texto_general(texto: str) -> str:
|
||||||
t = texto.strip()
|
# Colapsa espacios múltiples que deja el autocorrector y recorta extremos
|
||||||
|
t = " ".join(texto.split())
|
||||||
return "N/A" if t == "0" else t
|
return "N/A" if t == "0" else t
|
||||||
|
|
||||||
# --- 4. TECLADOS DINÁMICOS ---
|
# --- 4. TECLADOS DINÁMICOS ---
|
||||||
|
|||||||
Reference in New Issue
Block a user