Files
telegram_new_socias/modules/printer.py

119 lines
4.7 KiB
Python

import os
import requests
import smtplib
import ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from telegram import Update
from telegram.ext import ContextTypes, ConversationHandler, CommandHandler, MessageHandler, filters
from modules.database import log_request
# Webhook opcional para notificar el evento de impresión
WEBHOOK_PRINTS = [w.strip() for w in (os.getenv("WEBHOOK_PRINT", "")).split(",") if w.strip()]
# --- SMTP Configuration ---
SMTP_SERVER = os.getenv("SMTP_SERVER")
SMTP_PORT = int(os.getenv("SMTP_PORT", 465))
SMTP_USER = os.getenv("SMTP_USER")
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD")
# Permitimos PRINTER_EMAIL como alias legado para SMTP_RECIPIENT
SMTP_RECIPIENT = os.getenv("SMTP_RECIPIENT") or os.getenv("PRINTER_EMAIL")
# Estado
ESPERANDO_ARCHIVO = 1
async def start_print(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.effective_user
log_request(user.id, user.username, "print", update.message.text)
await update.message.reply_text("🖨️ **Servicio de Impresión**\n\nPor favor, envíame el archivo (PDF, DOCX o Imagen) que deseas imprimir/enviar.")
return ESPERANDO_ARCHIVO
async def recibir_archivo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.effective_user
archivo = update.message.document or update.message.photo[-1] # Toma documento o la foto más grande
file_id = archivo.file_id
file_name = getattr(archivo, 'file_name', f"foto_{file_id}.jpg")
await update.message.reply_text(f"Procesando *{file_name}*... un momento por favor.")
try:
if not all([SMTP_SERVER, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_RECIPIENT]):
raise RuntimeError("SMTP no configurado (falta SERVER/USER/PASSWORD/RECIPIENT).")
# 1. Descargar el archivo de Telegram
file_info = await context.bot.get_file(file_id)
file_url = file_info.file_path
file_content = requests.get(file_url).content
# 2. Construir el correo
msg = MIMEMultipart()
msg['From'] = SMTP_USER
msg['To'] = SMTP_RECIPIENT
msg['Subject'] = f"Nuevo archivo para imprimir de {user.full_name}"
# Cuerpo del correo
body = f"""
Hola,
El usuario {user.full_name} (Username: @{user.username}, ID: {user.id}) ha enviado un archivo para imprimir.
Nombre del archivo: {file_name}
Este correo ha sido generado automáticamente por Vanessa Bot.
"""
msg.attach(MIMEText(body, 'plain'))
# Adjuntar el archivo
attachment = MIMEApplication(file_content, Name=file_name)
attachment['Content-Disposition'] = f'attachment; filename="{file_name}"'
msg.attach(attachment)
# 3. Enviar el correo
ssl_context = ssl.create_default_context()
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT, context=ssl_context) as server:
server.login(SMTP_USER, SMTP_PASSWORD)
server.sendmail(SMTP_USER, SMTP_RECIPIENT, msg.as_string())
await update.message.reply_text(f"✅ Archivo *{file_name}* enviado a la impresora correctamente.")
except Exception as e:
print(f"Error al enviar correo: {e}") # Log para el admin
await update.message.reply_text("❌ Hubo un error al procesar tu archivo. Por favor, contacta a un administrador.")
return ConversationHandler.END
# Webhook de notificación (sin archivo, solo metadata)
if WEBHOOK_PRINTS:
payload = {
"accion": "PRINT",
"usuario": {
"id": user.id,
"username": user.username,
"nombre": user.full_name
},
"archivo": {
"nombre": file_name,
"telegram_file_id": file_id,
},
"enviado_via": "email",
"timestamp": update.message.date.isoformat() if update.message.date else None
}
for url in WEBHOOK_PRINTS:
try:
requests.post(url, json=payload, timeout=10).raise_for_status()
except Exception as e:
print(f"Error notificando webhook de impresión a {url}: {e}")
return ConversationHandler.END
async def cancelar(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Operación cancelada.")
return ConversationHandler.END
# Exportamos el handler
print_handler = ConversationHandler(
entry_points=[CommandHandler("print", start_print)],
states={ESPERANDO_ARCHIVO: [MessageHandler(filters.Document.ALL | filters.PHOTO, recibir_archivo)]},
fallbacks=[CommandHandler("cancelar", cancelar)]
)