20-sep: [fix] Bot Telegram control PC - confirmacion + watchdog apagado/encendido + doc autologon

This commit is contained in:
juanminsanz
2026-09-20 22:19:20 +02:00
parent 8412d3f657
commit ac876f59c6
5 changed files with 383 additions and 17 deletions

View File

@@ -12,6 +12,7 @@ Uso:
"""
import os
import sys
import asyncio
import requests
import subprocess
from dotenv import load_dotenv
@@ -65,33 +66,95 @@ async def menu(update: Update, context: ContextTypes.DEFAULT_TYPE):
)
async def apagar_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Apaga el PC"""
"""Apaga el PC con confirmación"""
query = update.callback_query if update.callback_query else None
# CONFIRMAR antes de apagar
keyboard = [
[
InlineKeyboardButton("✅ SÍ, apagar", callback_data='apagar_confirmar'),
InlineKeyboardButton("❌ Cancelar", callback_data='cancelar')
]
]
reply_markup = InlineKeyboardMarkup(keyboard)
mensaje = (
"⚠️ <b>CONFIRMAR APAGADO</b>\n\n"
"¿Seguro que quieres apagar el PC?\n\n"
"Se ejecutará:\n"
"🔹 Cerrar ventanas\n"
"🔹 Apagar luces (barras + cuartillo)\n"
"🔹 Apagar pantalla\n"
"🔹 Apagar regleta\n"
"🔹 Shutdown completo"
)
if query:
await query.answer("🔴 Apagando PC...")
msg = await query.message.reply_text("🔴 Apagando PC...")
await query.answer()
await query.message.edit_text(mensaje, parse_mode='HTML', reply_markup=reply_markup)
else:
msg = await update.message.reply_text("🔴 Apagando PC...")
await update.message.reply_text(mensaje, parse_mode='HTML', reply_markup=reply_markup)
async def apagar_pc_confirmar(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Ejecuta el apagado tras confirmación"""
query = update.callback_query
await query.answer("🔴 Apagando PC...")
msg = await query.message.edit_text("🔴 Apagando PC...")
try:
response = requests.post(HA_WEBHOOK_APAGAR, timeout=10)
if response.status_code == 200:
mensaje = (
"✅ <b>PC apagado correctamente</b>\n\n"
"🔹 Luces apagadas: barras, cuartillo\n"
"🔹 Regleta: apagada\n"
"🔹 PC: sin corriente"
"✅ <b>Apagado iniciado</b>\n\n"
"🔹 Luces: apagando\n"
"🔹 Pantalla: apagando\n"
"🔹 PC: shutdown en 10s\n\n"
"⏳ Verificando estado en 30s..."
)
await msg.edit_text(mensaje, parse_mode='HTML')
# WATCHDOG: comprobar estado tras 30 segundos
await asyncio.sleep(30)
# Verificar si realmente se apagó
try:
result = subprocess.run(
["powershell", "-Command", f"Test-Connection -ComputerName {PC_IP} -Count 1 -Quiet"],
capture_output=True,
timeout=5,
text=True
)
online = "True" in result.stdout
if online:
mensaje_final = (
"⚠️ <b>APAGADO FALLIDO</b>\n\n"
f"El PC sigue respondiendo en {PC_IP}\n"
"Puede que el apagado se cancelara."
)
else:
mensaje_final = (
"✅ <b>PC APAGADO CONFIRMADO</b>\n\n"
f"🔹 IP {PC_IP}: sin respuesta\n"
"🔹 Estado: Offline"
)
except:
mensaje_final = (
"✅ <b>Apagado completado</b>\n\n"
"No se pudo verificar estado (timeout)"
)
await msg.edit_text(mensaje_final, parse_mode='HTML')
else:
mensaje = f"❌ Error al apagar: HTTP {response.status_code}"
await msg.edit_text(mensaje, parse_mode='HTML')
except Exception as e:
mensaje = f"❌ Error: {e}"
await msg.edit_text(mensaje, parse_mode='HTML')
await msg.edit_text(mensaje, parse_mode='HTML')
async def encender_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Enciende el PC"""
"""Enciende el PC y verifica que arrancó"""
query = update.callback_query if update.callback_query else None
if query:
@@ -105,18 +168,63 @@ async def encender_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
if response.status_code == 200:
mensaje = (
"✅ <b>Proceso de encendido iniciado</b>\n\n"
"🔹 Regleta: encendida\n"
"🔹 Regleta: encendiendo\n"
"🔹 Esperando 60 segundos...\n"
"🔹 Wake-on-LAN enviado\n\n"
"⏳ El PC debería estar listo en ~2 minutos.\n"
"Usa /estado para verificar."
"🔹 Wake-on-LAN: enviando\n\n"
"⏳ Verificando en 90 segundos..."
)
await msg.edit_text(mensaje, parse_mode='HTML')
# WATCHDOG: esperar 90s y verificar si arrancó
await asyncio.sleep(90)
# Verificar si el PC arrancó
intentos = 0
max_intentos = 3
online = False
while intentos < max_intentos and not online:
try:
result = subprocess.run(
["powershell", "-Command", f"Test-Connection -ComputerName {PC_IP} -Count 2 -Quiet"],
capture_output=True,
timeout=10,
text=True
)
online = "True" in result.stdout
if not online:
intentos += 1
if intentos < max_intentos:
await asyncio.sleep(15)
except:
intentos += 1
if intentos < max_intentos:
await asyncio.sleep(15)
if online:
mensaje_final = (
"✅ <b>PC ENCENDIDO CORRECTAMENTE</b>\n\n"
f"🔹 IP {PC_IP}: responde\n"
"🔹 Estado: Online\n"
"🔹 Tiempo: ~{} segundos".format(90 + intentos * 15)
)
else:
mensaje_final = (
"❌ <b>ENCENDIDO FALLIDO</b>\n\n"
f"El PC no responde en {PC_IP}\n"
"Verifica:\n"
"🔹 Regleta encendida\n"
"🔹 PC físicamente apagado\n"
"🔹 Wake-on-LAN habilitado en BIOS"
)
await msg.edit_text(mensaje_final, parse_mode='HTML')
else:
mensaje = f"❌ Error al encender: HTTP {response.status_code}"
await msg.edit_text(mensaje, parse_mode='HTML')
except Exception as e:
mensaje = f"❌ Error: {e}"
await msg.edit_text(mensaje, parse_mode='HTML')
await msg.edit_text(mensaje, parse_mode='HTML')
async def estado_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Verifica si el PC está encendido"""
@@ -165,16 +273,26 @@ async def estado_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
await msg.edit_text(mensaje, parse_mode='HTML')
async def cancelar(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Cancela una operación y vuelve al menú"""
query = update.callback_query
await query.answer("Cancelado")
await menu(update, context)
async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Maneja los botones del menú"""
query = update.callback_query
if query.data == 'apagar':
await apagar_pc(update, context)
elif query.data == 'apagar_confirmar':
await apagar_pc_confirmar(update, context)
elif query.data == 'encender':
await encender_pc(update, context)
elif query.data == 'estado':
await estado_pc(update, context)
elif query.data == 'cancelar':
await cancelar(update, context)
def main():
"""Arranca el bot"""