03-sep: [videoclub] Buscador interactivo + agentes/skills OpenCode + aviso por voz

This commit is contained in:
juanjo
2026-09-03 20:25:35 +02:00
parent 808fdd1806
commit b1296a0a07
39 changed files with 4917 additions and 40 deletions

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import os
import subprocess
import sys
import threading
import time
import urllib.parse
@@ -182,23 +183,14 @@ def procesar(texto, chat_id):
procesar_pelis(chat_id)
elif t in ("series", "/series"):
procesar_series(chat_id)
elif t.startswith("pelicula ") or t.startswith("/pelicula "):
nombre = texto.split(" ", 1)[1].strip()
procesar_buscador_pelicula(nombre, chat_id)
elif t.startswith("serie ") or t.startswith("/serie "):
nombre = texto.split(" ", 1)[1].strip()
try:
import pelis
except Exception as e:
log(f"serie import error: {e}")
enviar("❌ No se pudo cargar el modulo pelis", chat_id)
return
enviar("🔎 Buscando la serie en el catálogo...", chat_id)
try:
mensajes, encontrada = pelis.buscar_serie(nombre)
except Exception as e:
log(f"serie buscar error: {e}")
enviar(f"❌ Error consultando el catálogo: {e}", chat_id)
return
for m in mensajes:
enviar(m, chat_id)
procesar_buscador_serie(nombre, chat_id)
elif t in ("novedades", "/novedades"):
procesar_novedades(chat_id)
elif t in ("ayuda", "/ayuda", "help", "/help"):
enviar("Comandos:\n"
"<b>estado</b> — estado de la Pi\n"
@@ -207,9 +199,9 @@ def procesar(texto, chat_id):
"<b>alarma &lt;mensaje&gt;</b> — secuencia completa (sirena x3)\n"
"<b>youtube &lt;URL&gt;</b> — reproduce YouTube y apaga al terminar\n"
"<b>descargar &lt;enlace&gt;</b> — añade a Download Station del NAS\n"
"<b>pelis</b> — novedades en castellano con comando listo\n"
"<b>series</b> — series en castellano con comando listo\n"
"<b>serie &lt;nombre&gt;</b> — temporadas/capitulos de una serie con enlaces\n"
"<b>pelicula &lt;nombre&gt;</b> — buscar pelicula y descargar\n"
"<b>serie &lt;nombre&gt;</b> — buscar serie con temporadas/capitulos\n"
"<b>novedades</b> — ultimas novedades del catalogo\n"
"<b>panorama</b> — fotos de las cámaras\n"
"<b>limpieza</b> — limpia procesos atascados de la Pi\n"
"<b>reboot</b> — reinicia la Pi (necesita confirmar con /confirmar-reboot)\n"
@@ -311,6 +303,99 @@ def procesar_pelis(chat_id):
threading.Timer(300, borrar, args=(chat_id, mid)).start()
def procesar_buscador_pelicula(nombre, chat_id):
"""Busca peliculas por nombre y muestra resultados numerados."""
try:
sys.path.insert(0, os.path.join(BASE, "..", "videoclub"))
import videoclub_buscador as vcb
except Exception as e:
log(f"videoclub_buscador import error: {e}")
enviar("❌ No se pudo cargar el modulo videoclub", chat_id)
return
enviar(f"🔎 Buscando <b>{nombre}</b> en el catálogo...", chat_id)
try:
resultados = vcb.buscar_peliculas(nombre)
mensajes = vcb.formatear_peliculas(resultados)
except Exception as e:
log(f"buscador pelicula error: {e}")
enviar(f"❌ Error consultando el catálogo: {e}", chat_id)
return
for m in mensajes:
enviar(m, chat_id)
if resultados:
log(f"BUSCADOR pelis '{nombre}': {len(resultados)} resultados")
def procesar_buscador_serie(nombre, chat_id):
"""Busca series por nombre y muestra temporadas/capitulos numerados."""
try:
sys.path.insert(0, os.path.join(BASE, "..", "videoclub"))
import videoclub_buscador as vcb
except Exception as e:
log(f"videoclub_buscador import error: {e}")
enviar("❌ No se pudo cargar el modulo videoclub", chat_id)
return
enviar(f"🔎 Buscando serie <b>{nombre}</b> en el catálogo...", chat_id)
try:
grupos = vcb.buscar_series(nombre)
mensajes = vcb.formatear_series(grupos)
except Exception as e:
log(f"buscador serie error: {e}")
enviar(f"❌ Error consultando el catálogo: {e}", chat_id)
return
for m in mensajes:
enviar(m, chat_id)
if grupos:
total_eps = sum(len(v) for v in grupos.values())
log(f"BUSCADOR series '{nombre}': {len(grupos)} series, {total_eps} capitulos")
def procesar_novedades(chat_id):
"""Muestra las ultimas novedades del catalogo."""
try:
sys.path.insert(0, os.path.join(BASE, "..", "videoclub"))
import videoclub_buscador as vcb
except Exception as e:
log(f"videoclub_buscador import error: {e}")
enviar("❌ No se pudo cargar el modulo videoclub", chat_id)
return
enviar("🎬 Consultando ultimas novedades...", chat_id)
try:
items = vcb.generar_novedades()
except Exception as e:
log(f"novedades error: {e}")
enviar(f"❌ Error consultando el catálogo: {e}", chat_id)
return
if not items:
enviar("No hay novedades recientes.", chat_id)
return
lineas = [f"🎬 <b>Ultimas novedades ({len(items)}):</b>", ""]
for i, it in enumerate(items, 1):
y = f" ({it['year']})" if it["year"] else ""
tipo = "📺" if it["tipo"] == "serie" else "🎬"
idioma = "cast." if it.get("castellano") else ""
enlace = it.get("enlace") or ""
lineas.append(f"{tipo} <b>{i}.</b> {it['clean']}{y} {idioma}")
if enlace:
lineas.append(f" <code>descargar {enlace}</code>")
texto = "\n".join(lineas)
# Trocear si es muy largo
CHUNK = 3500
partes = []
actual = []
long = 0
for linea in lineas:
if actual and long + len(linea) + 1 > CHUNK:
partes.append("\n".join(actual))
actual, long = [], 0
actual.append(linea)
long += len(linea) + 1
if actual:
partes.append("\n".join(actual))
for parte in partes:
enviar(parte, chat_id)
def monitor_temperatura():
while True:
time.sleep(300)