06-sep: [videoclub] temporada completa, rangos bajar X-Y, pelis solo castellano
This commit is contained in:
@@ -51,7 +51,8 @@ CALIDAD_MALA = re.compile(
|
|||||||
r"(CAMRip|TS\.|HDTS|Telesync|KinoRip|Screener|HDCAM|HC\b|r5|360p|240p)",
|
r"(CAMRip|TS\.|HDTS|Telesync|KinoRip|Screener|HDCAM|HC\b|r5|360p|240p)",
|
||||||
re.IGNORECASE)
|
re.IGNORECASE)
|
||||||
CASTELLANO = re.compile(
|
CASTELLANO = re.compile(
|
||||||
r"(Esp|Castellano|Span|Spanish|dual|lat|\bES\b|audio)", re.IGNORECASE)
|
r"(Esp[añ]ol|Castellano|Spanish|Latino|DualLat|\bdual\b|\bESS?\b|\bESP\b)",
|
||||||
|
re.IGNORECASE)
|
||||||
INGLES = re.compile(r"(Eng|English|Ingl[eé]s|\bEN\b)", re.IGNORECASE)
|
INGLES = re.compile(r"(Eng|English|Ingl[eé]s|\bEN\b)", re.IGNORECASE)
|
||||||
OTRO_IDIOMA = re.compile(
|
OTRO_IDIOMA = re.compile(
|
||||||
r"(Ita\b|MIRCrew|RO\s?EN|South Wind|Silver Zero|Francais|Deutsch|Portugu[eê]s)",
|
r"(Ita\b|MIRCrew|RO\s?EN|South Wind|Silver Zero|Francais|Deutsch|Portugu[eê]s)",
|
||||||
@@ -193,7 +194,7 @@ def buscar_peliculas(termino, items=None):
|
|||||||
continue
|
continue
|
||||||
if not it["buena_calidad"]:
|
if not it["buena_calidad"]:
|
||||||
continue
|
continue
|
||||||
if not (it.get("castellano") or bool(INGLES.search(it.get("name", "")))):
|
if not it.get("castellano"):
|
||||||
continue
|
continue
|
||||||
clean = (it.get("clean") or "").lower()
|
clean = (it.get("clean") or "").lower()
|
||||||
name = (it.get("name") or "").lower()
|
name = (it.get("name") or "").lower()
|
||||||
@@ -294,11 +295,13 @@ def formatear_series(grupos):
|
|||||||
etiqueta = f"S{temp:02d}E{cap:02d}"
|
etiqueta = f"S{temp:02d}E{cap:02d}"
|
||||||
else:
|
else:
|
||||||
etiqueta = it["clean"]
|
etiqueta = it["clean"]
|
||||||
lineas.append(f" <b>{num_global}.</b> {etiqueta} — {resto}")
|
idioma = " · cast." if it.get("castellano") else ""
|
||||||
|
lineas.append(f" <b>{num_global}.</b> {etiqueta} — {resto}{idioma}")
|
||||||
num_global += 1
|
num_global += 1
|
||||||
lineas.append("")
|
lineas.append("")
|
||||||
|
|
||||||
lineas.append("Responde <b>/torrents NUMERO</b> de episodio para ver opciones y descargar.")
|
lineas.append("Responde <b>/torrents NUMERO</b> de episodio para ver opciones y descargar.")
|
||||||
|
lineas.append("O <b>/temporada N</b> (temporada completa) o <b>/bajar X-Y</b> (rango).")
|
||||||
return trocear_texto(lineas)
|
return trocear_texto(lineas)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
@@ -800,8 +801,11 @@ def procesar(texto, chat_id):
|
|||||||
n = _int_arg(texto)
|
n = _int_arg(texto)
|
||||||
procesar_torrents(n, chat_id)
|
procesar_torrents(n, chat_id)
|
||||||
elif t.startswith("bajar ") or t.startswith("/bajar "):
|
elif t.startswith("bajar ") or t.startswith("/bajar "):
|
||||||
|
spec = texto.split(" ", 1)[1].strip() if " " in texto else ""
|
||||||
|
procesar_bajar(spec, chat_id)
|
||||||
|
elif t.startswith("temporada ") or t.startswith("/temporada "):
|
||||||
n = _int_arg(texto)
|
n = _int_arg(texto)
|
||||||
procesar_bajar(n, chat_id)
|
procesar_temporada(n, chat_id)
|
||||||
elif comando == "aspiradora":
|
elif comando == "aspiradora":
|
||||||
procesar_aspiradora(argumento, chat_id)
|
procesar_aspiradora(argumento, chat_id)
|
||||||
elif comando in ("menu", "menú", "inicio", "start") and not argumento:
|
elif comando in ("menu", "menú", "inicio", "start") and not argumento:
|
||||||
@@ -823,8 +827,8 @@ def procesar(texto, chat_id):
|
|||||||
" ✏️ Ej: <code>/genero</code> → 1 (pelis) → 12 (Horror)\n"
|
" ✏️ Ej: <code>/genero</code> → 1 (pelis) → 12 (Horror)\n"
|
||||||
"<b>3.</b> <code>torrents <n></code> — torrents del resultado n\n"
|
"<b>3.</b> <code>torrents <n></code> — torrents del resultado n\n"
|
||||||
" ✏️ Ej: <code>/torrents 1</code>\n"
|
" ✏️ Ej: <code>/torrents 1</code>\n"
|
||||||
"<b>4.</b> <code>bajar <n></code> — descargar al NAS el torrent n\n"
|
"<b>4.</b> <code>bajar <n></code> — descargar al NAS el torrent n\n"
|
||||||
" ✏️ Ej: <code>/bajar 1</code>\n"
|
" ✏️ Ej: <code>/bajar 1</code>, <code>/bajar 2-5</code>, <code>/temporada 1</code>\n"
|
||||||
"<b>5.</b> <code>pelicula <nombre></code> — buscar película (catálogo)\n"
|
"<b>5.</b> <code>pelicula <nombre></code> — buscar película (catálogo)\n"
|
||||||
" ✏️ Ej: <code>/pelicula ant-man</code>\n"
|
" ✏️ Ej: <code>/pelicula ant-man</code>\n"
|
||||||
"<b>6.</b> <code>serie <nombre></code> — buscar serie (catálogo)\n"
|
"<b>6.</b> <code>serie <nombre></code> — buscar serie (catálogo)\n"
|
||||||
@@ -1274,51 +1278,148 @@ def procesar_torrents(n, chat_id):
|
|||||||
log(f"TORRENTS '{r['name']}': {len(torrents)} torrents")
|
log(f"TORRENTS '{r['name']}': {len(torrents)} torrents")
|
||||||
|
|
||||||
|
|
||||||
def procesar_bajar(n, chat_id):
|
def procesar_bajar(spec, chat_id):
|
||||||
"""Descarga el torrent numero n al NAS (Download Station via magnet)."""
|
"""Descarga al NAS: numero, rango (2-5) o episodios directos."""
|
||||||
estado = ultimos_torrents.get(chat_id)
|
estado = ultimos_torrents.get(chat_id)
|
||||||
if not estado or n is None or n < 1 or n > len(estado["torrents"]):
|
titulos = ultima_titulos.get(chat_id) or {}
|
||||||
|
if estado and estado.get("torrents"):
|
||||||
|
idx = _parse_indices(spec, len(estado["torrents"]))
|
||||||
|
if not idx:
|
||||||
|
enviar("Uso: <b>/bajar <numero></b> o <b>/bajar X-Y</b>.",
|
||||||
|
chat_id)
|
||||||
|
return
|
||||||
|
buenas, malas = [], []
|
||||||
|
for i in idx:
|
||||||
|
uri, etiqueta = _bajar_torrent(estado["torrents"][i - 1],
|
||||||
|
estado.get("titulo") or "")
|
||||||
|
if not uri:
|
||||||
|
malas.append(etiqueta)
|
||||||
|
continue
|
||||||
|
ok, _ = _bajar_uri(uri, etiqueta)
|
||||||
|
(buenas if ok else malas).append(etiqueta)
|
||||||
|
log(f"BAJAR '{estado.get('titulo')}' torrent {i}: ok={ok}")
|
||||||
|
partes = []
|
||||||
|
if buenas:
|
||||||
|
partes.append(f"📥 Añadidos al NAS ({len(buenas)}):\n" +
|
||||||
|
"\n".join(f"• {b}" for b in buenas))
|
||||||
|
if malas:
|
||||||
|
partes.append("❌ Fallaron:\n" +
|
||||||
|
"\n".join(f"• {m}" for m in malas))
|
||||||
|
enviar("\n".join(partes) or "❌ Nada que descargar.", chat_id)
|
||||||
|
return
|
||||||
|
if titulos.get("origen") == "catalogo" and titulos.get("results"):
|
||||||
|
resultados = titulos["results"]
|
||||||
|
idx = _parse_indices(spec, len(resultados))
|
||||||
|
if not idx:
|
||||||
|
enviar("Uso: <b>/bajar <numero></b>, <b>/bajar X-Y</b> o "
|
||||||
|
"<b>/temporada N</b>.", chat_id)
|
||||||
|
return
|
||||||
|
buenas, malas = [], []
|
||||||
|
for i in idx:
|
||||||
|
it = resultados[i - 1]
|
||||||
|
nombre = it.get("clean") or it.get("name") or f"episodio {i}"
|
||||||
|
if not it.get("enlace"):
|
||||||
|
malas.append(f"{nombre} (sin enlace)")
|
||||||
|
continue
|
||||||
|
ok, _ = _bajar_uri(it["enlace"], nombre)
|
||||||
|
(buenas if ok else malas).append(nombre)
|
||||||
|
log(f"BAJAR catalogo '{nombre}': ok={ok}")
|
||||||
|
partes = []
|
||||||
|
if buenas:
|
||||||
|
partes.append(f"📥 Añadidos al NAS ({len(buenas)}):\n" +
|
||||||
|
"\n".join(f"• {b}" for b in buenas))
|
||||||
|
if malas:
|
||||||
|
partes.append("❌ Fallaron:\n" +
|
||||||
|
"\n".join(f"• {m}" for m in malas))
|
||||||
|
enviar("\n".join(partes) or "❌ Nada que descargar.", chat_id)
|
||||||
|
return
|
||||||
enviar("Primero usa <b>/busca</b>, <b>/pelicula</b>, <b>/serie</b>, "
|
enviar("Primero usa <b>/busca</b>, <b>/pelicula</b>, <b>/serie</b>, "
|
||||||
"<b>/novedades</b> o <b>/genero</b>, luego "
|
"<b>/novedades</b> o <b>/genero</b>, luego "
|
||||||
"<b>/torrents <numero></b>.", chat_id)
|
"<b>/torrents <numero></b>.", chat_id)
|
||||||
return
|
|
||||||
t = estado["torrents"][n - 1]
|
|
||||||
if t.get("enlace") and not t.get("info_hash"):
|
def _parse_indices(spec, total, maximo=10):
|
||||||
# Enlace directo de catalogo: al NAS sin magnet.
|
"""'3' -> [3]; '2-5' o '2:5' -> [2..5]. Recorta al total (max 10)."""
|
||||||
|
spec = str(spec or "").strip()
|
||||||
|
m = re.match(r"(\d+)\s*[-:]\s*(\d+)$", spec)
|
||||||
|
if m:
|
||||||
|
a, b = int(m.group(1)), int(m.group(2))
|
||||||
|
if a > b:
|
||||||
|
a, b = b, a
|
||||||
|
elif spec.isdigit():
|
||||||
|
a = b = int(spec)
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
a = max(a, 1)
|
||||||
|
b = min(b, total)
|
||||||
|
if a > b:
|
||||||
|
return []
|
||||||
|
return list(range(a, min(b, a + maximo - 1) + 1))
|
||||||
|
|
||||||
|
|
||||||
|
def _bajar_uri(uri, etiqueta):
|
||||||
|
"""Anade un magnet/enlace al NAS. Devuelve (ok, etiqueta)."""
|
||||||
try:
|
try:
|
||||||
import nas_dl
|
import nas_dl
|
||||||
ok = nas_dl.add_torrent(t["enlace"])
|
ok = nas_dl.add_torrent(uri)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"bajar error: {e}")
|
log(f"bajar error: {e}")
|
||||||
enviar(f"❌ Error al anadir al NAS: {e}", chat_id)
|
return False, f"{etiqueta} (error: {e})"
|
||||||
return
|
return bool(ok), etiqueta
|
||||||
if ok:
|
|
||||||
enviar(f"📥 Añadido al NAS: <b>{t.get('filename') or estado['titulo']}</b>.",
|
|
||||||
chat_id)
|
def _bajar_torrent(t, titulo):
|
||||||
else:
|
"""Resuelve un item de ultimos_torrents a (uri, etiqueta)."""
|
||||||
enviar("❌ No se pudo añadir al NAS.", chat_id)
|
if t.get("enlace") and not t.get("info_hash"):
|
||||||
return
|
return t["enlace"], t.get("filename") or titulo
|
||||||
try:
|
try:
|
||||||
gol = _import_global_buscar()
|
gol = _import_global_buscar()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"global_buscar import error: {e}")
|
log(f"global_buscar import error: {e}")
|
||||||
enviar("❌ No se pudo cargar el modulo", chat_id)
|
return None, "sin modulo"
|
||||||
|
tam = f"{t['size']:.1f}GB" if t.get("size") else "?"
|
||||||
|
return gol.magnet_de(t), f"{t.get('filename') or titulo} ({t.get('calidad')}, {tam})"
|
||||||
|
|
||||||
|
|
||||||
|
def procesar_temporada(n, chat_id):
|
||||||
|
"""Descarga la temporada N completa de la ultima serie del catalogo."""
|
||||||
|
titulos = ultima_titulos.get(chat_id) or {}
|
||||||
|
if titulos.get("origen") != "catalogo" or not titulos.get("results"):
|
||||||
|
enviar("Primero busca una <b>/serie</b> y luego "
|
||||||
|
"<b>/temporada <N></b>.", chat_id)
|
||||||
|
return
|
||||||
|
if n is None or n < 1:
|
||||||
|
enviar("Uso: <b>/temporada <N></b>.", chat_id)
|
||||||
return
|
return
|
||||||
magnet = gol.magnet_de(t)
|
|
||||||
log(f"BAJAR '{estado['titulo']}' torrent {n}: {magnet[:60]}...")
|
|
||||||
try:
|
try:
|
||||||
import nas_dl
|
sys.path.insert(0, os.path.join(BASE, "..", "videoclub"))
|
||||||
ok = nas_dl.add_torrent(magnet)
|
import videoclub_buscador as vcb
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"bajar error: {e}")
|
log(f"videoclub_buscador import error: {e}")
|
||||||
enviar(f"❌ Error al anadir al NAS: {e}", chat_id)
|
enviar("❌ No se pudo cargar el modulo videoclub", chat_id)
|
||||||
return
|
return
|
||||||
if ok:
|
capitulos = []
|
||||||
tamaño = f"{t['size']:.1f}GB" if t.get("size") else "?"
|
for it in titulos["results"]:
|
||||||
enviar(f"📥 Añadido al NAS: <b>{t['filename'] or estado['titulo']}</b> "
|
try:
|
||||||
f"({t['calidad']}, {tamaño}).", chat_id)
|
temp, _cap = vcb.parsear_episodio(it.get("name") or "")
|
||||||
else:
|
except Exception:
|
||||||
enviar("❌ No se pudo añadir al NAS.", chat_id)
|
temp = 0
|
||||||
|
if temp == n and it.get("enlace"):
|
||||||
|
capitulos.append(it)
|
||||||
|
if not capitulos:
|
||||||
|
enviar(f"❌ No hay capitulos con enlace en la temporada {n}.",
|
||||||
|
chat_id)
|
||||||
|
return
|
||||||
|
buenas, malas = [], []
|
||||||
|
for it in capitulos[:25]:
|
||||||
|
nombre = it.get("clean") or it.get("name") or "capitulo"
|
||||||
|
ok, _ = _bajar_uri(it["enlace"], nombre)
|
||||||
|
(buenas if ok else malas).append(nombre)
|
||||||
|
partes = [f"📥 Temporada {n} al NAS ({len(buenas)} capitulos)."]
|
||||||
|
if malas:
|
||||||
|
partes.append("❌ Fallaron: " + ", ".join(malas))
|
||||||
|
enviar("\n".join(partes), chat_id)
|
||||||
|
log(f"TEMPORADA {n}: {len(buenas)} ok, {len(malas)} fallo")
|
||||||
|
|
||||||
|
|
||||||
def monitor_temperatura():
|
def monitor_temperatura():
|
||||||
|
|||||||
Reference in New Issue
Block a user