03-sep: [comando] /descargar ver progreso de descargas + listar_descargas en nas_dl
This commit is contained in:
@@ -139,6 +139,70 @@ def add_torrent(uri, session=None):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def human_size(n):
|
||||||
|
"""Formatea bytes a una unidad legible."""
|
||||||
|
n = float(n or 0)
|
||||||
|
for u in ("B", "KB", "MB", "GB", "TB"):
|
||||||
|
if n < 1024:
|
||||||
|
return f"{n:.1f}{u}"
|
||||||
|
n /= 1024
|
||||||
|
return f"{n:.1f}PB"
|
||||||
|
|
||||||
|
|
||||||
|
def listar_descargas(hablar_solo_activas=True, session=None):
|
||||||
|
"""Devuelve (lineas_texto, activas). Lista las tareas de Download Station
|
||||||
|
con estado, porcentaje de progreso, tamaño descargado y velocidad.
|
||||||
|
`progress` se calcula con downloaded_pieces/total_pieces (fiable en NAS)."""
|
||||||
|
if not session:
|
||||||
|
session = login()
|
||||||
|
if not session:
|
||||||
|
return ["❌ No se pudo autenticar con Download Station."], []
|
||||||
|
try:
|
||||||
|
r = _api("/webapi/DownloadStation/task.cgi", {
|
||||||
|
"api": "SYNO.DownloadStation.Task",
|
||||||
|
"version": "3",
|
||||||
|
"method": "list",
|
||||||
|
"additional": "detail,transfer",
|
||||||
|
}, session=session)
|
||||||
|
if not r.get("success"):
|
||||||
|
return [f"❌ Error al listar: {r.get('error')}"], []
|
||||||
|
except Exception as e:
|
||||||
|
return [f"❌ Error al consultar el NAS: {e}"], []
|
||||||
|
tareas = r.get("data", {}).get("tasks", []) or []
|
||||||
|
lineas, activas, resto = [], [], []
|
||||||
|
for t in tareas:
|
||||||
|
titulo = t.get("title") or ""
|
||||||
|
estado = t.get("status") or "?"
|
||||||
|
detail = (t.get("additional") or {}).get("detail") or {}
|
||||||
|
transfer = (t.get("additional") or {}).get("transfer") or {}
|
||||||
|
total_pieces = detail.get("total_pieces") or 0
|
||||||
|
done_pieces = transfer.get("downloaded_pieces") or 0
|
||||||
|
pct = (done_pieces * 100.0 / total_pieces) if total_pieces else 0
|
||||||
|
size = transfer.get("size_downloaded") or 0
|
||||||
|
speed = transfer.get("speed_download") or 0
|
||||||
|
if estado == "downloading":
|
||||||
|
activas.append(f"▶️ <b>{pct:.1f}%</b> {human_size(size)} ⬇️{speed // 1024} KB/s\n"
|
||||||
|
f" {titulo}")
|
||||||
|
else:
|
||||||
|
resto.append((estado, pct, size, titulo))
|
||||||
|
if activas:
|
||||||
|
lineas.append("📥 <b>DESCARGANDO</b>")
|
||||||
|
lineas.extend(activas)
|
||||||
|
lineas.append("")
|
||||||
|
if not hablar_solo_activas:
|
||||||
|
lineas.append("📁 Otras tareas:")
|
||||||
|
for estado, pct, size, titulo in resto:
|
||||||
|
icono = {"finished": "✅", "error": "❌", "paused": "⏸️",
|
||||||
|
"seeding": "🌱"}.get(estado, "•")
|
||||||
|
if estado == "finished":
|
||||||
|
lineas.append(f"{icono} {titulo}")
|
||||||
|
else:
|
||||||
|
lineas.append(f"{icono} {estado} ({pct:.0f}%) — {titulo}")
|
||||||
|
if not activas:
|
||||||
|
lineas.append("No hay torrents descargándose ahora mismo.")
|
||||||
|
return lineas, activas
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
|
|||||||
@@ -80,17 +80,20 @@ def estado():
|
|||||||
|
|
||||||
|
|
||||||
def enviar(texto, chat_id):
|
def enviar(texto, chat_id):
|
||||||
try:
|
# Trocea mensajes largos (Telegram limita a ~4096 chars) para no fallar en silencio
|
||||||
r = requests.post(
|
for i in range(0, len(texto), 4000):
|
||||||
f"https://api.telegram.org/bot{TOKEN}/sendMessage",
|
bloque = texto[i:i + 4000]
|
||||||
data={"chat_id": chat_id, "text": texto, "parse_mode": "HTML"},
|
try:
|
||||||
timeout=10,
|
r = requests.post(
|
||||||
)
|
f"https://api.telegram.org/bot{TOKEN}/sendMessage",
|
||||||
d = r.json()
|
data={"chat_id": chat_id, "text": bloque, "parse_mode": "HTML"},
|
||||||
if d.get("ok"):
|
timeout=10,
|
||||||
return d["result"].get("message_id")
|
)
|
||||||
except Exception as e:
|
d = r.json()
|
||||||
print("Error enviando:", e)
|
if d.get("ok"):
|
||||||
|
return d["result"].get("message_id")
|
||||||
|
except Exception as e:
|
||||||
|
print("Error enviando:", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -204,6 +207,10 @@ def procesar(texto, chat_id):
|
|||||||
else:
|
else:
|
||||||
ok = mandar_youtube(url)
|
ok = mandar_youtube(url)
|
||||||
enviar("🎬 YouTube lanzado en la TV ✅" if ok else "❌ No se pudo lanzar YouTube", chat_id)
|
enviar("🎬 YouTube lanzado en la TV ✅" if ok else "❌ No se pudo lanzar YouTube", chat_id)
|
||||||
|
elif t in ("descargar", "/descargar"):
|
||||||
|
import nas_dl
|
||||||
|
lineas, _act = nas_dl.listar_descargas(hablar_solo_activas=True)
|
||||||
|
enviar("\n".join(lineas), chat_id)
|
||||||
elif t.startswith("descargar ") or t.startswith("/descargar "):
|
elif t.startswith("descargar ") or t.startswith("/descargar "):
|
||||||
uri = texto.split(" ", 1)[1].strip()
|
uri = texto.split(" ", 1)[1].strip()
|
||||||
if not uri:
|
if not uri:
|
||||||
@@ -253,31 +260,33 @@ def procesar(texto, chat_id):
|
|||||||
" ✏️ Ej: <code>/serie breaking bad</code>\n"
|
" ✏️ Ej: <code>/serie breaking bad</code>\n"
|
||||||
"<b>7.</b> <code>novedades</code> — últimas novedades del catálogo\n"
|
"<b>7.</b> <code>novedades</code> — últimas novedades del catálogo\n"
|
||||||
" ✏️ Ej: <code>/novedades</code>\n\n"
|
" ✏️ Ej: <code>/novedades</code>\n\n"
|
||||||
"━━━ 🖥️ NAS / DESCARGAS ━━━\n"
|
"━━━ 🖥️ NAS / DESCARGAS ━━━\n"
|
||||||
"<b>8.</b> <code>descargar <enlace></code> — añade a Download Station\n"
|
"<b>8.</b> <code>descargar</code> — torrents descargándose y su progreso\n"
|
||||||
" ✏️ Ej: <code>/descargar magnet:?xt=urn:btih:...</code>\n\n"
|
" ✏️ Ej: <code>/descargar</code>\n"
|
||||||
"━━━ 📺 TV ━━━\n"
|
"<b>9.</b> <code>descargar <enlace></code> — añade a Download Station\n"
|
||||||
"<b>9.</b> <code>tv <mensaje></code> — mensaje rápido a la tele\n"
|
" ✏️ Ej: <code>/descargar magnet:?xt=urn:btih:...</code>\n\n"
|
||||||
" ✏️ Ej: <code>/tv la cena está lista</code>\n"
|
"━━━ 📺 TV ━━━\n"
|
||||||
"<b>10.</b> <code>alarma <mensaje></code> — secuencia completa (sirena x3)\n"
|
"<b>10.</b> <code>tv <mensaje></code> — mensaje rápido a la tele\n"
|
||||||
" ✏️ Ej: <code>/alarma vienen a por vosotros</code>\n"
|
" ✏️ Ej: <code>/tv la cena está lista</code>\n"
|
||||||
"<b>11.</b> <code>youtube <URL></code> — reproduce YouTube en la TV\n"
|
"<b>11.</b> <code>alarma <mensaje></code> — secuencia completa (sirena x3)\n"
|
||||||
" ✏️ Ej: <code>/youtube https://youtu.be/xxxx</code>\n\n"
|
" ✏️ Ej: <code>/alarma vienen a por vosotros</code>\n"
|
||||||
"━━━ 🛠️ SISTEMA ━━━\n"
|
"<b>12.</b> <code>youtube <URL></code> — reproduce YouTube en la TV\n"
|
||||||
"<b>12.</b> <code>estado</code> — estado de la Pi\n"
|
" ✏️ Ej: <code>/youtube https://youtu.be/xxxx</code>\n\n"
|
||||||
" ✏️ Ej: <code>/estado</code>\n"
|
"━━━ 🛠️ SISTEMA ━━━\n"
|
||||||
"<b>13.</b> <code>temperatura</code> — temperatura de la Pi\n"
|
"<b>13.</b> <code>estado</code> — estado de la Pi\n"
|
||||||
" ✏️ Ej: <code>/temperatura</code>\n"
|
" ✏️ Ej: <code>/estado</code>\n"
|
||||||
"<b>14.</b> <code>panorama</code> — fotos de las cámaras\n"
|
"<b>14.</b> <code>temperatura</code> — temperatura de la Pi\n"
|
||||||
" ✏️ Ej: <code>/panorama</code>\n"
|
" ✏️ Ej: <code>/temperatura</code>\n"
|
||||||
"<b>15.</b> <code>limpieza</code> — limpia procesos atascados\n"
|
"<b>15.</b> <code>panorama</code> — fotos de las cámaras\n"
|
||||||
" ✏️ Ej: <code>/limpieza</code>\n"
|
" ✏️ Ej: <code>/panorama</code>\n"
|
||||||
"<b>16.</b> <code>servicios</code> — estado de los servicios\n"
|
"<b>16.</b> <code>limpieza</code> — limpia procesos atascados\n"
|
||||||
" ✏️ Ej: <code>/servicios</code>\n"
|
" ✏️ Ej: <code>/limpieza</code>\n"
|
||||||
"<b>17.</b> <code>reboot</code> — reinicia la Pi\n"
|
"<b>17.</b> <code>servicios</code> — estado de los servicios\n"
|
||||||
" ✏️ Ej: <code>/reboot</code> → confirmar con <code>/confirmar-reboot</code>\n"
|
" ✏️ Ej: <code>/servicios</code>\n"
|
||||||
"<b>18.</b> <code>ayuda</code> — este índice\n"
|
"<b>18.</b> <code>reboot</code> — reinicia la Pi\n"
|
||||||
" ✏️ Ej: <code>/ayuda</code>",
|
" ✏️ Ej: <code>/reboot</code> → confirmar con <code>/confirmar-reboot</code>\n"
|
||||||
|
"<b>19.</b> <code>ayuda</code> — este índice\n"
|
||||||
|
" ✏️ Ej: <code>/ayuda</code>",
|
||||||
chat_id)
|
chat_id)
|
||||||
elif t in ("servicios", "/servicios"):
|
elif t in ("servicios", "/servicios"):
|
||||||
estado_svc = sh("systemctl is-active pi-bot tv-api autossh-tunel")
|
estado_svc = sh("systemctl is-active pi-bot tv-api autossh-tunel")
|
||||||
|
|||||||
Reference in New Issue
Block a user