204 lines
6.6 KiB
Python
204 lines
6.6 KiB
Python
"""
|
|
Bot de Telegram para controlar el PC remotamente.
|
|
|
|
Comandos:
|
|
- /apagar - Apaga PC completo (luces + regleta)
|
|
- /encender - Enciende PC (regleta + WoL)
|
|
- /estado - Verifica si el PC está encendido
|
|
- /menu - Muestra menú con botones
|
|
|
|
Uso:
|
|
python telegram_bot_pc.py
|
|
"""
|
|
import os
|
|
import sys
|
|
import requests
|
|
import subprocess
|
|
from dotenv import load_dotenv
|
|
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
|
from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes
|
|
|
|
# Cargar .env
|
|
dotenv_path = r"C:\Users\juanm\Documents\GitHub\biblioteca_negocio_prolongo\.env"
|
|
load_dotenv(dotenv_path)
|
|
|
|
# Configuración
|
|
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_PC_TOKEN")
|
|
TELEGRAM_USER_ID = os.getenv("TELEGRAM_USER_ID") # ID de Juanjo
|
|
HA_WEBHOOK_APAGAR = "http://185.187.169.109:8123/api/webhook/apagar-pc-juanjo"
|
|
HA_WEBHOOK_ENCENDER = "http://185.187.169.109:8123/api/webhook/encender-pc-juanjo"
|
|
PC_IP = "192.168.1.239" # IP del PC sobremesa
|
|
|
|
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""Comando /start"""
|
|
await menu(update, context)
|
|
|
|
async def menu(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""Muestra el menú principal"""
|
|
keyboard = [
|
|
[
|
|
InlineKeyboardButton("🔴 Apagar PC", callback_data='apagar'),
|
|
InlineKeyboardButton("🟢 Encender PC", callback_data='encender')
|
|
],
|
|
[
|
|
InlineKeyboardButton("📊 Estado PC", callback_data='estado')
|
|
]
|
|
]
|
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
|
|
|
mensaje = (
|
|
"🖥️ <b>Control Remoto PC</b>\n\n"
|
|
"Elige una opción:"
|
|
)
|
|
|
|
if update.callback_query:
|
|
await update.callback_query.message.edit_text(
|
|
mensaje,
|
|
parse_mode='HTML',
|
|
reply_markup=reply_markup
|
|
)
|
|
else:
|
|
await update.message.reply_text(
|
|
mensaje,
|
|
parse_mode='HTML',
|
|
reply_markup=reply_markup
|
|
)
|
|
|
|
async def apagar_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""Apaga el PC"""
|
|
query = update.callback_query if update.callback_query else None
|
|
|
|
if query:
|
|
await query.answer("🔴 Apagando PC...")
|
|
msg = await query.message.reply_text("🔴 Apagando PC...")
|
|
else:
|
|
msg = await update.message.reply_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"
|
|
)
|
|
else:
|
|
mensaje = f"❌ Error al apagar: HTTP {response.status_code}"
|
|
except Exception as e:
|
|
mensaje = f"❌ Error: {e}"
|
|
|
|
await msg.edit_text(mensaje, parse_mode='HTML')
|
|
|
|
async def encender_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""Enciende el PC"""
|
|
query = update.callback_query if update.callback_query else None
|
|
|
|
if query:
|
|
await query.answer("🟢 Encendiendo PC...")
|
|
msg = await query.message.reply_text("🟢 Encendiendo PC...")
|
|
else:
|
|
msg = await update.message.reply_text("🟢 Encendiendo PC...")
|
|
|
|
try:
|
|
response = requests.post(HA_WEBHOOK_ENCENDER, timeout=10)
|
|
if response.status_code == 200:
|
|
mensaje = (
|
|
"✅ <b>Proceso de encendido iniciado</b>\n\n"
|
|
"🔹 Regleta: encendida\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."
|
|
)
|
|
else:
|
|
mensaje = f"❌ Error al encender: HTTP {response.status_code}"
|
|
except Exception as e:
|
|
mensaje = f"❌ Error: {e}"
|
|
|
|
await msg.edit_text(mensaje, parse_mode='HTML')
|
|
|
|
async def estado_pc(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""Verifica si el PC está encendido"""
|
|
query = update.callback_query if update.callback_query else None
|
|
|
|
if query:
|
|
await query.answer("📊 Verificando...")
|
|
msg = await query.message.reply_text("📊 Verificando estado...")
|
|
else:
|
|
msg = await update.message.reply_text("📊 Verificando estado...")
|
|
|
|
# Ping al PC usando PowerShell (más confiable en Windows)
|
|
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 = (
|
|
"✅ <b>PC ENCENDIDO</b>\n\n"
|
|
f"🔹 IP: {PC_IP}\n"
|
|
"🔹 Responde a ping\n"
|
|
"🔹 Estado: Online"
|
|
)
|
|
else:
|
|
mensaje = (
|
|
"🔴 <b>PC APAGADO</b>\n\n"
|
|
f"🔹 IP: {PC_IP}\n"
|
|
"🔹 No responde a ping\n"
|
|
"🔹 Estado: Offline"
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
mensaje = (
|
|
"⚠️ <b>TIMEOUT</b>\n\n"
|
|
f"🔹 IP: {PC_IP}\n"
|
|
"🔹 No responde (>5s)\n"
|
|
"🔹 Estado: Probablemente apagado"
|
|
)
|
|
except Exception as e:
|
|
mensaje = f"❌ Error al verificar estado: {e}"
|
|
|
|
await msg.edit_text(mensaje, parse_mode='HTML')
|
|
|
|
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 == 'encender':
|
|
await encender_pc(update, context)
|
|
elif query.data == 'estado':
|
|
await estado_pc(update, context)
|
|
|
|
def main():
|
|
"""Arranca el bot"""
|
|
if not TELEGRAM_BOT_TOKEN:
|
|
print("ERROR: Falta TELEGRAM_BOT_PC_TOKEN en .env")
|
|
return
|
|
|
|
print("Iniciando bot de Telegram para control de PC...")
|
|
|
|
app = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
|
|
|
|
# Comandos
|
|
app.add_handler(CommandHandler("start", start))
|
|
app.add_handler(CommandHandler("menu", menu))
|
|
app.add_handler(CommandHandler("apagar", apagar_pc))
|
|
app.add_handler(CommandHandler("encender", encender_pc))
|
|
app.add_handler(CommandHandler("estado", estado_pc))
|
|
|
|
# Botones
|
|
app.add_handler(CallbackQueryHandler(button_handler))
|
|
|
|
print("Bot iniciado. Presiona Ctrl+C para detener.")
|
|
app.run_polling()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|