05-sep: [infra] configurar Raspberry Pi y documentar flota
This commit is contained in:
@@ -5,6 +5,7 @@ import sys
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
import json
|
||||
|
||||
import requests
|
||||
|
||||
@@ -13,6 +14,7 @@ ultima_titulos = {} # chat_id -> {'query':..., 'results':[...]}
|
||||
ultimos_torrents = {} # chat_id -> {'titulo':..., 'torrents':[...]}
|
||||
flujo_genero = {} # chat_id -> 'esperando_tipo' | 'esperando_genero' | None
|
||||
flujo_genero_tipo = {} # chat_id -> 'movie' | 'series' (tipo ya elegido)
|
||||
panel_descargas = {} # chat_id -> estado del panel editable
|
||||
|
||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||
LOG = os.path.join(BASE, "bot.log")
|
||||
@@ -100,6 +102,148 @@ def enviar(texto, chat_id):
|
||||
return ultimo_id
|
||||
|
||||
|
||||
def teclado_descargas():
|
||||
return {
|
||||
"inline_keyboard": [
|
||||
[
|
||||
{"text": "🔄 Actualizar", "callback_data": "dl:refresh"},
|
||||
{"text": "▶️ Activas", "callback_data": "dl:active"},
|
||||
],
|
||||
[
|
||||
{"text": "📁 Todas", "callback_data": "dl:all"},
|
||||
{"text": "✖️ Cerrar", "callback_data": "dl:close"},
|
||||
],
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def enviar_panel_descargas(texto, chat_id):
|
||||
try:
|
||||
r = requests.post(
|
||||
f"https://api.telegram.org/bot{TOKEN}/sendMessage",
|
||||
data={
|
||||
"chat_id": chat_id,
|
||||
"text": texto,
|
||||
"parse_mode": "HTML",
|
||||
"reply_markup": json.dumps(teclado_descargas()),
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
d = r.json()
|
||||
if d.get("ok"):
|
||||
return d["result"].get("message_id")
|
||||
log(f"Telegram panel send error: {d.get('description', d)}")
|
||||
except Exception as e:
|
||||
log(f"Telegram panel send exception: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def editar_panel_descargas(chat_id, message_id, texto):
|
||||
try:
|
||||
r = requests.post(
|
||||
f"https://api.telegram.org/bot{TOKEN}/editMessageText",
|
||||
data={
|
||||
"chat_id": chat_id,
|
||||
"message_id": message_id,
|
||||
"text": texto,
|
||||
"parse_mode": "HTML",
|
||||
"reply_markup": json.dumps(teclado_descargas()),
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
d = r.json()
|
||||
if not d.get("ok") and "not modified" not in d.get("description", "").lower():
|
||||
log(f"Telegram panel edit error: {d.get('description', d)}")
|
||||
return d.get("ok", False)
|
||||
except Exception as e:
|
||||
log(f"Telegram panel edit exception: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def responder_callback(callback_id):
|
||||
try:
|
||||
requests.post(
|
||||
f"https://api.telegram.org/bot{TOKEN}/answerCallbackQuery",
|
||||
data={"callback_query_id": callback_id},
|
||||
timeout=10,
|
||||
)
|
||||
except Exception as e:
|
||||
log(f"Telegram callback error: {e}")
|
||||
|
||||
|
||||
def texto_panel_descargas(modo="active"):
|
||||
import nas_dl
|
||||
lineas, activas = nas_dl.listar_descargas(
|
||||
hablar_solo_activas=(modo == "active")
|
||||
)
|
||||
encabezado = "📥 <b>DESCARGAS DEL NAS</b>"
|
||||
if modo == "active":
|
||||
encabezado += " · ACTIVAS"
|
||||
texto = encabezado + "\n\n" + "\n".join(lineas)
|
||||
texto += f"\n\n🕒 Actualizado: <code>{time.strftime('%H:%M:%S')}</code>"
|
||||
return texto, activas
|
||||
|
||||
|
||||
def abrir_panel_descargas(chat_id):
|
||||
anterior = panel_descargas.pop(chat_id, None)
|
||||
if anterior:
|
||||
anterior["stop"].set()
|
||||
try:
|
||||
texto, _activas = texto_panel_descargas()
|
||||
message_id = enviar_panel_descargas(texto, chat_id)
|
||||
if not message_id:
|
||||
enviar("❌ No se pudo abrir el panel de descargas.", chat_id)
|
||||
return
|
||||
estado_panel = {
|
||||
"message_id": message_id,
|
||||
"modo": "active",
|
||||
"stop": threading.Event(),
|
||||
}
|
||||
panel_descargas[chat_id] = estado_panel
|
||||
threading.Thread(
|
||||
target=monitor_panel_descargas,
|
||||
args=(chat_id, estado_panel),
|
||||
daemon=True,
|
||||
).start()
|
||||
except Exception as e:
|
||||
log(f"panel descargas error: {e}")
|
||||
enviar(f"❌ Error en el panel de descargas: {e}", chat_id)
|
||||
|
||||
|
||||
def monitor_panel_descargas(chat_id, estado_panel):
|
||||
while not estado_panel["stop"].wait(20):
|
||||
try:
|
||||
texto, activas = texto_panel_descargas(estado_panel["modo"])
|
||||
editar_panel_descargas(chat_id, estado_panel["message_id"], texto)
|
||||
if not activas:
|
||||
break
|
||||
except Exception as e:
|
||||
log(f"monitor panel descargas error: {e}")
|
||||
|
||||
|
||||
def procesar_callback(callback):
|
||||
callback_id = callback.get("id")
|
||||
mensaje = callback.get("message") or {}
|
||||
chat_id = (mensaje.get("chat") or {}).get("id")
|
||||
accion = (callback.get("data") or "").split(":", 1)[-1]
|
||||
responder_callback(callback_id)
|
||||
estado_panel = panel_descargas.get(chat_id)
|
||||
if not estado_panel:
|
||||
return
|
||||
if accion == "close":
|
||||
estado_panel["stop"].set()
|
||||
panel_descargas.pop(chat_id, None)
|
||||
borrar(chat_id, estado_panel["message_id"])
|
||||
return
|
||||
if accion in ("active", "all"):
|
||||
estado_panel["modo"] = "active" if accion == "active" else "all"
|
||||
try:
|
||||
texto, _activas = texto_panel_descargas(estado_panel["modo"])
|
||||
editar_panel_descargas(chat_id, estado_panel["message_id"], texto)
|
||||
except Exception as e:
|
||||
log(f"callback panel descargas error: {e}")
|
||||
|
||||
|
||||
def borrar(chat_id, message_id):
|
||||
try:
|
||||
requests.post(
|
||||
@@ -213,6 +357,8 @@ def procesar(texto, chat_id):
|
||||
else:
|
||||
ok = mandar_youtube(url)
|
||||
enviar("🎬 YouTube lanzado en la TV ✅" if ok else "❌ No se pudo lanzar YouTube", chat_id)
|
||||
elif t in ("descargas", "/descargas") or (comando == "descargar" and not argumento):
|
||||
abrir_panel_descargas(chat_id)
|
||||
elif comando == "descargar":
|
||||
try:
|
||||
import nas_dl
|
||||
@@ -220,11 +366,6 @@ def procesar(texto, chat_id):
|
||||
ok = nas_dl.add_torrent(argumento)
|
||||
enviar("📥 Añadido a Download Station del NAS ✅" if ok
|
||||
else "❌ No se pudo añadir al NAS. Revisa <code>bot.log</code>.", chat_id)
|
||||
else:
|
||||
# Incluye también pendientes, pausadas y terminadas para que
|
||||
# el usuario pueda ver el estado real de cada torrent.
|
||||
lineas, _act = nas_dl.listar_descargas(hablar_solo_activas=False)
|
||||
enviar("\n".join(lineas), chat_id)
|
||||
except Exception as e:
|
||||
log(f"descargar error: {e}")
|
||||
enviar(f"❌ Error en Download Station: {e}", chat_id)
|
||||
@@ -269,8 +410,8 @@ def procesar(texto, chat_id):
|
||||
"<b>7.</b> <code>novedades</code> — últimas novedades del catálogo\n"
|
||||
" ✏️ Ej: <code>/novedades</code>\n\n"
|
||||
"━━━ 🖥️ NAS / DESCARGAS ━━━\n"
|
||||
"<b>8.</b> <code>descargar</code> — torrents descargándose y su progreso\n"
|
||||
" ✏️ Ej: <code>/descargar</code>\n"
|
||||
"<b>8.</b> <code>descargas</code> — panel con progreso y botones\n"
|
||||
" ✏️ Ej: <code>/descargas</code> o <code>/descargar</code>\n"
|
||||
"<b>9.</b> <code>descargar <enlace></code> — añade a Download Station\n"
|
||||
" ✏️ Ej: <code>/descargar magnet:?xt=urn:btih:...</code>\n\n"
|
||||
"━━━ 📺 TV ━━━\n"
|
||||
@@ -646,6 +787,9 @@ def main():
|
||||
offset = upd["update_id"] + 1
|
||||
guardar_offset(offset)
|
||||
log(f"UPDATE {upd.get('update_id')}")
|
||||
if upd.get("callback_query"):
|
||||
procesar_callback(upd["callback_query"])
|
||||
continue
|
||||
msg = upd.get("message") or upd.get("channel_post")
|
||||
if not msg:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user