mirror of
https://github.com/marcogll/telegram_new_socias.git
synced 2026-01-13 13:15:16 +00:00
feat: Integrate Google Sheets for duplicate chat ID verification and update main actions keyboard logic
This commit is contained in:
@@ -4,6 +4,9 @@ TELEGRAM_ADMIN_CHAT_ID=TELEGRAM_ADMIN_CHAT_ID
|
||||
OPENAI_API_KEY=SK......
|
||||
GOOGLE_API_KEY=AIzaSyBqH5...
|
||||
|
||||
# URL de la hoja de cálculo de Google para verificar duplicados
|
||||
GOOGLE_SHEET_URL=https://docs.google.com/spreadsheets/d/1iVHnNoAF4sVVhb2kcclthznYFUKetmhsM6b2ZUCXd-0/edit?gid=370216950#gid=370216950
|
||||
|
||||
|
||||
# Webhooks de n8n (puedes agregar más aquí en el futuro)
|
||||
# Usa WEBHOOK_ONBOARDING (o el alias WEBHOOK_CONTRATO si ya lo tienes así)
|
||||
|
||||
7
main.py
7
main.py
@@ -18,7 +18,7 @@ from telegram.ext import Application, Defaults, CommandHandler, ContextTypes
|
||||
# --- IMPORTAR HABILIDADES ---
|
||||
from modules.onboarding import onboarding_handler
|
||||
from modules.rh_requests import vacaciones_handler, permiso_handler
|
||||
from modules.database import log_request
|
||||
from modules.database import log_request, chat_id_exists # Importar chat_id_exists
|
||||
from modules.ui import main_actions_keyboard
|
||||
# from modules.finder import finder_handler (Si lo creas después)
|
||||
|
||||
@@ -79,13 +79,14 @@ async def menu_principal(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"👩💼 **Hola, soy Vanessa. ¿En qué puedo ayudarte hoy?**\n\n"
|
||||
"Toca un botón para continuar 👇"
|
||||
)
|
||||
await update.message.reply_text(texto, reply_markup=main_actions_keyboard())
|
||||
is_registered = chat_id_exists(user.id)
|
||||
await update.message.reply_text(texto, reply_markup=main_actions_keyboard(is_registered=is_registered))
|
||||
|
||||
async def post_init(application: Application):
|
||||
# Mantén los comandos rápidos disponibles en el menú de Telegram
|
||||
await application.bot.set_my_commands([
|
||||
BotCommand("start", "Mostrar menú principal"),
|
||||
BotCommand("welcome", "Registro de nuevas empleadas"),
|
||||
# BotCommand("welcome", "Registro de nuevas empleadas"), # Se maneja dinámicamente
|
||||
BotCommand("vacaciones", "Solicitar vacaciones"),
|
||||
BotCommand("permiso", "Solicitar permiso por horas"),
|
||||
BotCommand("links", "Links útiles"),
|
||||
|
||||
@@ -4,10 +4,62 @@ from datetime import datetime
|
||||
from sqlalchemy import Column, DateTime, Integer, MetaData, String, create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
import gspread
|
||||
from google.oauth2.service_account import Credentials
|
||||
|
||||
# Configuración de logging
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||
|
||||
# --- GOOGLE SHEETS SETUP ---
|
||||
GSHEET_URL = os.getenv("GOOGLE_SHEET_URL")
|
||||
GOOGLE_CREDENTIALS_FILE = os.getenv("GOOGLE_CREDENTIALS_FILE", "google_credentials.json")
|
||||
SHEET_COLUMN_INDEX = 40 # AN is the 40th column
|
||||
|
||||
def get_gsheet_client():
|
||||
"""Retorna un cliente de gspread autenticado o None si falla."""
|
||||
if not GSHEET_URL:
|
||||
logging.warning("GOOGLE_SHEET_URL no está configurada. La verificación de duplicados está deshabilitada.")
|
||||
return None
|
||||
|
||||
if not os.path.exists(GOOGLE_CREDENTIALS_FILE):
|
||||
logging.warning(f"No se encontró el archivo de credenciales '{GOOGLE_CREDENTIALS_FILE}'. La verificación de duplicados está deshabilitada.")
|
||||
return None
|
||||
|
||||
try:
|
||||
scopes = ["https://www.googleapis.com/auth/spreadsheets.readonly"]
|
||||
creds = Credentials.from_service_account_file(GOOGLE_CREDENTIALS_FILE, scopes=scopes)
|
||||
client = gspread.authorize(creds)
|
||||
return client
|
||||
except Exception as e:
|
||||
logging.error(f"Error al autenticar con Google Sheets: {e}")
|
||||
return None
|
||||
|
||||
def chat_id_exists(chat_id: int) -> bool:
|
||||
"""Verifica si un chat_id de Telegram ya existe en la columna AN de la hoja de cálculo."""
|
||||
client = get_gsheet_client()
|
||||
if not client:
|
||||
return False # Si no hay cliente, no podemos verificar, así que asumimos que no existe.
|
||||
|
||||
try:
|
||||
spreadsheet = client.open_by_url(GSHEET_URL)
|
||||
worksheet = spreadsheet.get_worksheet(0) # Primera hoja
|
||||
|
||||
# Obtener todos los valores de la columna AN (índice 40)
|
||||
chat_ids_in_sheet = worksheet.col_values(SHEET_COLUMN_INDEX)
|
||||
|
||||
# El ID de chat puede venir como número o texto, así que comparamos como string
|
||||
return str(chat_id) in chat_ids_in_sheet
|
||||
|
||||
except gspread.exceptions.SpreadsheetNotFound:
|
||||
logging.error(f"No se pudo encontrar la hoja de cálculo en la URL proporcionada.")
|
||||
return False
|
||||
except Exception as e:
|
||||
logging.error(f"Error al leer la hoja de cálculo: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# --- DATABASE (MySQL) SETUP ---
|
||||
|
||||
# Base para los modelos declarativos
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ from telegram.ext import (
|
||||
Defaults,
|
||||
)
|
||||
|
||||
from modules.database import log_request
|
||||
from modules.database import log_request, chat_id_exists
|
||||
from modules.ui import main_actions_keyboard
|
||||
|
||||
# --- 1. CARGA DE ENTORNO ---
|
||||
@@ -173,9 +173,20 @@ TECLADO_RELACION_EMERGENCIA = ReplyKeyboardMarkup(
|
||||
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
user = update.effective_user
|
||||
context.user_data.clear()
|
||||
log_request(user.id, user.username, "welcome", update.message.text)
|
||||
|
||||
# --- VERIFICACIÓN DE DUPLICADOS ---
|
||||
if chat_id_exists(user.id):
|
||||
await update.message.reply_text(
|
||||
"👩💼 Hola de nuevo. Ya tienes un registro activo en nuestro sistema.\n\n"
|
||||
"Si crees que es un error o necesitas hacer cambios, por favor contacta a tu manager o a RH directamente. "
|
||||
"¡Gracias!",
|
||||
reply_markup=main_actions_keyboard()
|
||||
)
|
||||
return ConversationHandler.END
|
||||
|
||||
context.user_data.clear()
|
||||
|
||||
context.user_data["metadata"] = {
|
||||
"telegram_id": user.id,
|
||||
"username": user.username or "N/A",
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
from telegram import ReplyKeyboardMarkup
|
||||
|
||||
|
||||
def main_actions_keyboard() -> ReplyKeyboardMarkup:
|
||||
def main_actions_keyboard(is_registered: bool = False) -> ReplyKeyboardMarkup:
|
||||
"""Teclado inferior con comandos directos (un toque lanza el flujo)."""
|
||||
return ReplyKeyboardMarkup(
|
||||
[
|
||||
["/welcome"],
|
||||
keyboard = []
|
||||
if not is_registered:
|
||||
keyboard.append(["/welcome"])
|
||||
|
||||
keyboard.extend([
|
||||
["/vacaciones", "/permiso"],
|
||||
["/links", "/start"],
|
||||
],
|
||||
])
|
||||
|
||||
return ReplyKeyboardMarkup(
|
||||
keyboard,
|
||||
resize_keyboard=True,
|
||||
)
|
||||
|
||||
@@ -5,3 +5,5 @@ SQLAlchemy
|
||||
mysql-connector-python
|
||||
google-generativeai
|
||||
openai
|
||||
gspread
|
||||
google-auth-oauthlib
|
||||
Reference in New Issue
Block a user