elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Scripting
| | |-+  [AYUDA] Problemas parte codigo python
0 Usuarios y 2 Visitantes están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [AYUDA] Problemas parte codigo python  (Leído 1,810 veces)
Cronno

Desconectado Desconectado

Mensajes: 3


Ver Perfil
[AYUDA] Problemas parte codigo python
« en: 28 Abril 2025, 01:33 am »

Muy buenas expertos.

No entiendo mucho de python, pero mediante IA hice esto para un bot de telegram donde lista libros por tirulos, año, autor, caratula....

El problema es que no consigo hacer que las busquedas por autor genere una lista oordenada de todos los autores que hay. El resto de busquedas funcionan perfectamente (Listado de libros ordenados por autor y Listado de libros por año) pero para que añada por autor termina liándola la IA de una u otra forma y deja de funcionar.

Alguien sabría del codigo a poner en este codigo completo?
Como dato decir que tanto el token como la lista los agarra de archivos externos (.env y json) aunque eso se aprecia en el código:

import os
import json
import unicodedata
import logging
import re
from telegram import Update
from telegram.ext import ApplicationBuilder, MessageHandler, filters, CommandHandler, CallbackContext
from dotenv import load_dotenv
from fuzzywuzzy import process, fuzz

# Configuración del logging
logging.basicConfig(format="%(asctime)s - %(levelname)s - %(message)s", level=logging.INFO)

# Cargar el token desde el archivo .env
load_dotenv()
TOKEN = os.getenv("TOKEN")

# Ruta del archivo de libros
LIBROS_FILE = os.path.join(os.path.dirname(__file__), "libros.json")

# Función para cargar libros desde el archivo JSON
def cargar_libros():
    try:
        with open(LIBROS_FILE, "r", encoding="utf-8") as f:
            data = json.load(f)
            if not isinstance(data, dict):
                raise ValueError("⚠️ El archivo JSON debe contener un diccionario con los libros.")
            return data
    except Exception as e:
        logging.error(f"⚠️ Error al cargar libros: {e}")
        return {}

# Función para limpiar el texto eliminando acentos y caracteres especiales
def limpiar_texto(texto):
    texto = ''.join(c for c in unicodedata.normalize('NFD', texto) if unicodedata.category(c) != 'Mn').lower()
    texto = re.sub(r"[^a-zA-Z0-9\s]", "", texto)  # Elimina caracteres especiales
    return texto.strip()

# Manejo de errores
async def manejar_error(update: Update, context: CallbackContext):
    logging.error(f"⚠️ Ocurrió un error: {context.error}")

# 📖 Listado de libros ordenados por autor
async def listado(update: Update, context):
    libros = cargar_libros()
    if not libros:
        await update.message.reply_text("❌ No hay libros disponibles.", parse_mode="Markdown")
        return

    respuesta = f"🔎 {len(libros)} libros disponibles:\n\n"
    libros_ordenados = sorted(libros.items(), key=lambda item: limpiar_texto(item[1]["autor"]))
    autor_actual = None

    for titulo, datos in libros_ordenados:
        if datos["autor"] != autor_actual:
            autor_actual = datos["autor"]
            respuesta += f"\n🖊 *{autor_actual}*\n"

        respuesta += f"📚 [{titulo}](t.me/{context.bot.username}?start={titulo.replace(' ', '_')}) 📅 {datos['año']}\n"

    await update.message.reply_text(respuesta, parse_mode="Markdown")

# 📆 Listado de libros por año
async def epoca(update: Update, context):
    libros = cargar_libros()
    if not libros:
        await update.message.reply_text("❌ No hay libros disponibles.", parse_mode="Markdown")
        return

    args = context.args
    año_filtrado = args[0] if args and args[0].isdigit() else None

    if año_filtrado:
        libros_filtrados = {titulo: datos for titulo, datos in libros.items() if str(datos["año"]) == año_filtrado}
        if not libros_filtrados:
            await update.message.reply_text(f"❌ No hay libros disponibles para el año {año_filtrado}.", parse_mode="Markdown")
            return

        respuesta = f"🔎 {len(libros_filtrados)} libros disponibles en {año_filtrado}:\n\n"
        libros_ordenados = sorted(libros_filtrados.items(), key=lambda item: item[1]["año"])
    else:
        respuesta = f"🔎 {len(libros)} libros disponibles:\n\n"
        libros_ordenados = sorted(libros.items(), key=lambda item: item[1]["año"])

    año_actual = None

    for titulo, datos in libros_ordenados:
        if datos["año"] != año_actual:
            año_actual = datos["año"]
            respuesta += f"\n📅 *{año_actual}*\n"

        respuesta += f"📚 [{titulo}](t.me/{context.bot.username}?start={titulo.replace(' ', '_')}) 🖊 {datos['autor']}\n"

    await update.message.reply_text(respuesta, parse_mode="Markdown")

# 🔍 Búsqueda mejorada con tolerancia a errores tipográficos
async def buscar(update: Update, context):
    libros = cargar_libros()
    consulta = limpiar_texto(update.message.text.strip())

    comandos_a_ignorar = ["/listado", "/epoca", "/ayuda", "/start"]
    for comando in comandos_a_ignorar:
        consulta = consulta.replace(limpiar_texto(comando), "").strip()

    if not consulta:
        return

    # Ajuste de búsqueda con umbral de similitud reducido a 60-65% para mayor tolerancia a errores
    resultados = [r for r in process.extract(consulta, libros.keys(), limit=5, scorer=fuzz.WRatio) if r[1] >= 65]

    if not resultados:
        await update.message.reply_text("❌ No encontré ningún libro que coincida con tu búsqueda.")
        return

    respuesta = f"🔎 {len(resultados)} libros similares encontrados:\n\n"

    for titulo, puntuacion in resultados:
        datos = libros[titulo]
        respuesta += f"📖 [{titulo}](t.me/{context.bot.username}?start={titulo.replace(' ', '_')}) 🖊 {datos['autor']} 📅 {datos['año']} (🔎 Similitud: {puntuacion}%)\n"

    await update.message.reply_text(respuesta, parse_mode="Markdown")

# 🚀 Mostrar información del libro
async def start(update: Update, context):
    args = context.args  
    if args:
        titulo = " ".join(args).replace("_", " ").strip()  
        libros = cargar_libros()

        titulo_real = next((key for key in libros.keys() if limpiar_texto(key) == limpiar_texto(titulo)), None)

        if titulo_real:
            link = libros[titulo_real].get("link", "❌ No hay enlace disponible.")
            portada = libros[titulo_real].get("portada", None)

            respuesta = f"📖 *{titulo_real}*\n🔗 {link}"
            
            if portada and portada.startswith("http"):
                await update.message.reply_photo(photo=portada, caption=respuesta, parse_mode="Markdown")
            else:
                await update.message.reply_text(respuesta, parse_mode="Markdown")
        else:
            await update.message.reply_text("❌ No encontré ese libro en la lista.", parse_mode="Markdown")
    else:
        await ayuda(update, context)

# 📌 Enviar mensaje de ayuda
async def ayuda(update: Update, context):
    respuesta = """🛠 *Comandos disponibles:*  
- 📜 /ayuda → Muestra este listado.  
- 📖 /listado → Lista los libros por autor.  
- 📆 /epoca → Lista los libros por año (/epoca AÑO para filtrar).  
- 🔍 Escribe el título o una parte para buscar un libro."""  

    mensaje = await update.message.reply_text(respuesta, parse_mode="Markdown")

    try:
        await mensaje.pin()
    except Exception as e:
        logging.warning(f"⚠️ No se pudo anclar el mensaje de ayuda: {e}")

# 🔧 Configuración del bot
def main():
    app = ApplicationBuilder().token(TOKEN).build()

    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("listado", listado))
    app.add_handler(CommandHandler("epoca", epoca))
    app.add_handler(CommandHandler("ayuda", ayuda))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, buscar))

    app.add_error_handler(manejar_error)  

    logging.info("✅ Bot iniciado correctamente...")
    app.run_polling()

if __name__ == "__main__":
    main()


« Última modificación: 29 Abril 2025, 03:17 am por Cronno » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines