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......
|
OPENAI_API_KEY=SK......
|
||||||
GOOGLE_API_KEY=AIzaSyBqH5...
|
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)
|
# Webhooks de n8n (puedes agregar más aquí en el futuro)
|
||||||
# Usa WEBHOOK_ONBOARDING (o el alias WEBHOOK_CONTRATO si ya lo tienes así)
|
# 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 ---
|
# --- IMPORTAR HABILIDADES ---
|
||||||
from modules.onboarding import onboarding_handler
|
from modules.onboarding import onboarding_handler
|
||||||
from modules.rh_requests import vacaciones_handler, permiso_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.ui import main_actions_keyboard
|
||||||
# from modules.finder import finder_handler (Si lo creas después)
|
# 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"
|
"👩💼 **Hola, soy Vanessa. ¿En qué puedo ayudarte hoy?**\n\n"
|
||||||
"Toca un botón para continuar 👇"
|
"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):
|
async def post_init(application: Application):
|
||||||
# Mantén los comandos rápidos disponibles en el menú de Telegram
|
# Mantén los comandos rápidos disponibles en el menú de Telegram
|
||||||
await application.bot.set_my_commands([
|
await application.bot.set_my_commands([
|
||||||
BotCommand("start", "Mostrar menú principal"),
|
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("vacaciones", "Solicitar vacaciones"),
|
||||||
BotCommand("permiso", "Solicitar permiso por horas"),
|
BotCommand("permiso", "Solicitar permiso por horas"),
|
||||||
BotCommand("links", "Links útiles"),
|
BotCommand("links", "Links útiles"),
|
||||||
|
|||||||
@@ -4,10 +4,62 @@ from datetime import datetime
|
|||||||
from sqlalchemy import Column, DateTime, Integer, MetaData, String, create_engine
|
from sqlalchemy import Column, DateTime, Integer, MetaData, String, create_engine
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
import gspread
|
||||||
|
from google.oauth2.service_account import Credentials
|
||||||
|
|
||||||
# Configuración de logging
|
# Configuración de logging
|
||||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
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 para los modelos declarativos
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from telegram.ext import (
|
|||||||
Defaults,
|
Defaults,
|
||||||
)
|
)
|
||||||
|
|
||||||
from modules.database import log_request
|
from modules.database import log_request, chat_id_exists
|
||||||
from modules.ui import main_actions_keyboard
|
from modules.ui import main_actions_keyboard
|
||||||
|
|
||||||
# --- 1. CARGA DE ENTORNO ---
|
# --- 1. CARGA DE ENTORNO ---
|
||||||
@@ -173,9 +173,20 @@ TECLADO_RELACION_EMERGENCIA = ReplyKeyboardMarkup(
|
|||||||
|
|
||||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||||
user = update.effective_user
|
user = update.effective_user
|
||||||
context.user_data.clear()
|
|
||||||
log_request(user.id, user.username, "welcome", update.message.text)
|
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"] = {
|
context.user_data["metadata"] = {
|
||||||
"telegram_id": user.id,
|
"telegram_id": user.id,
|
||||||
"username": user.username or "N/A",
|
"username": user.username or "N/A",
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
from telegram import ReplyKeyboardMarkup
|
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)."""
|
"""Teclado inferior con comandos directos (un toque lanza el flujo)."""
|
||||||
|
keyboard = []
|
||||||
|
if not is_registered:
|
||||||
|
keyboard.append(["/welcome"])
|
||||||
|
|
||||||
|
keyboard.extend([
|
||||||
|
["/vacaciones", "/permiso"],
|
||||||
|
["/links", "/start"],
|
||||||
|
])
|
||||||
|
|
||||||
return ReplyKeyboardMarkup(
|
return ReplyKeyboardMarkup(
|
||||||
[
|
keyboard,
|
||||||
["/welcome"],
|
|
||||||
["/vacaciones", "/permiso"],
|
|
||||||
["/links", "/start"],
|
|
||||||
],
|
|
||||||
resize_keyboard=True,
|
resize_keyboard=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ SQLAlchemy
|
|||||||
mysql-connector-python
|
mysql-connector-python
|
||||||
google-generativeai
|
google-generativeai
|
||||||
openai
|
openai
|
||||||
|
gspread
|
||||||
|
google-auth-oauthlib
|
||||||
Reference in New Issue
Block a user