¿Te imaginas escribir desde el móvil “crea un archivo notas Comprar pan” y que aparezca en tu ordenador? ¿O mandar ejecuta procesos y recibir al instante los programas que más CPU consumen? Se puede hacer con un bot de Telegram y un script de Python de unas 90 líneas. En este tutorial lo montamos paso a paso, con los errores que me encontré por el camino y cómo solucionarlos.
Qué vas a necesitar
- Un Mac con Python 3 instalado (yo he usado Python 3.12)
- Una cuenta de Telegram en el móvil
- Unos 20 minutos
Qué podrá hacer tu bot
| Mensaje que envías | Qué hace |
|---|---|
crea un archivo notas Comprar pan | Crea notas.txt con ese texto |
crea una carpeta fotos | Crea la carpeta fotos |
ejecuta procesos | Lista los procesos que más CPU consumen |
ejecuta disco | Muestra el espacio libre en disco |
ejecuta uptime | Indica cuánto lleva encendido el Mac |
ejecuta fecha | Devuelve la fecha y hora del sistema |
ejecuta bateria | Muestra el estado de la batería |
Paso 1: crear el bot con BotFather
Todos los bots de Telegram se registran con BotFather, el bot oficial para esto. Solo lo necesitas una vez.
- En Telegram, busca @BotFather (con el check azul de verificado).
- Escribe
/newbot. - Elige un nombre para el bot (por ejemplo, “Mi bot de archivos”).
- Elige un nombre de usuario que termine en
bot(por ejemplo,mi_archivos_bot). - BotFather te enviará un token con este aspecto:
123456789:AAExampleTokenLooksLikeThisXXXXXXXXXXXX
⚠️ Copia el token completo, empezando por los números y con los dos puntos. Si copias solo la parte que empieza por AA..., Telegram lo rechazará con un error de “Invalid token”.
⚠️ No compartas nunca tu token. Quien lo tenga controla tu bot. Si se te escapa, en BotFather usa /mybots → tu bot → API Token → Revoke current token para generar uno nuevo.
Paso 2: preparar la carpeta e instalar la librería
Abre el Terminal del Mac y ejecuta:
bash
mkdir ~/telegram
cd ~/telegram
pip3 install python-telegram-bot
Paso 3: averiguar tu ID de Telegram
El bot solo debe obedecerte a ti, y para eso necesita tu ID numérico de Telegram.
Opción A (rápida): escribe a @userinfobot en Telegram y te responderá con tu Id. A veces estos bots fallan; si no te responde, usa la opción B.
Opción B (siempre funciona): usa tu propio bot para que te lo diga.
- Crea un archivo llamado
miid.pydentro de la carpetatelegramcon este contenido:
python
import os
from telegram.ext import ApplicationBuilder, MessageHandler, filters
async def responder(update, context):
await update.message.reply_text(f"Tu ID es: {update.effective_user.id}")
app = ApplicationBuilder().token(os.environ["TELEGRAM_TOKEN"]).build()
app.add_handler(MessageHandler(filters.ALL, responder))
app.run_polling()
- Ejecútalo con tu token completo:
bash
export TELEGRAM_TOKEN="NUMEROS:RESTO_DEL_TOKEN"
python3 miid.py
- En el móvil, abre tu bot, pulsa Start y escríbele “hola”. Te responderá con tu ID.
- Vuelve al Terminal y pulsa Ctrl + C para pararlo.
⚠️ No llames a ningún script token.py (ni telegram.py, random.py, json.py…). Python ya tiene módulos internos con esos nombres y tu archivo los tapa, lo que provoca un error de importación circular que parece no tener sentido.
Paso 4: un aviso antes del código: no ejecutes “lo que sea”
Lo primero que se le ocurre a cualquiera es que el bot ejecute directamente el texto que le llega. Es mala idea. Si alguien accediera a tu cuenta de Telegram, o hubiera un fallo en el script, tendría control total de tu ordenador.
Por eso este bot funciona con una lista cerrada de comandos permitidos que defines tú:
- Solo se ejecuta lo que está en la lista. Todo lo demás se rechaza.
- Los comandos se lanzan sin pasar por la shell, así que no se puede colar nada extra en el mensaje.
- Cada comando tiene un tiempo máximo de 15 segundos.
- La respuesta se recorta para no inundar el chat.
- El bot solo obedece a tu ID de Telegram.
- Los archivos y carpetas solo se crean dentro de una carpeta fija, y el bot nunca sobrescribe lo que ya existe.
Una nota sobre Windows y Mac: si buscas cómo hacerlo, verás ejemplos con Get-Process, que es un comando de PowerShell (Windows). En un Mac el equivalente es ps, que es el que usamos aquí.
Paso 5: el script del bot
Crea un archivo bot.py dentro de la carpeta telegram con este código:
python
import os
import re
import subprocess
from datetime import datetime
from pathlib import Path
from telegram import Update
from telegram.ext import ApplicationBuilder, MessageHandler, ContextTypes, filters
TOKEN = os.environ["TELEGRAM_TOKEN"]
MI_ID = int(os.environ["TELEGRAM_USER_ID"])
BASE = Path.home() / "Documents" / "telegram"
BASE.mkdir(parents=True, exist_ok=True)
# Lista cerrada: solo se pueden ejecutar estos comandos
COMANDOS = {
"procesos": ["ps", "-axo", "pid,%cpu,%mem,comm", "-r"], # ordenados por CPU
"disco": ["df", "-h"],
"uptime": ["uptime"],
"fecha": ["date"],
"bateria": ["pmset", "-g", "batt"],
}
MAX_LINEAS = 20
def limpiar(nombre: str) -> str:
return re.sub(r"[^\w\-]", "", nombre)
def ejecutar(nombre: str) -> str:
try:
r = subprocess.run(
COMANDOS[nombre], capture_output=True, text=True, timeout=15
)
except subprocess.TimeoutExpired:
return "El comando tardó demasiado y se canceló."
salida = (r.stdout or r.stderr).strip()
lineas = salida.splitlines()[:MAX_LINEAS]
return "\n".join(lineas)[:3500] or "(sin salida)"
async def manejar(update: Update, context: ContextTypes.DEFAULT_TYPE):
# Ignorar a cualquiera que no seas tú
if update.effective_user.id != MI_ID:
return
texto = update.message.text.strip()
# --- Ejecutar comando de la lista ---
m = re.match(r"(?i)^ejecuta\s+(\S+)", texto)
if m:
nombre = m.group(1).lower()
if nombre not in COMANDOS:
await update.message.reply_text(
"Comandos disponibles: " + ", ".join(COMANDOS)
)
return
await update.message.reply_text(ejecutar(nombre))
return
# --- Crear carpeta ---
m = re.match(r"(?i)^crea una carpeta(?:\s+(\S+))?", texto)
if m:
nombre = limpiar(m.group(1) or "")
if not nombre:
nombre = datetime.now().strftime("carpeta-%Y%m%d-%H%M%S")
ruta = BASE / nombre
if ruta.exists():
await update.message.reply_text(f"Ya existe: {ruta}")
return
ruta.mkdir()
await update.message.reply_text(f"Carpeta creada: {ruta}")
return
# --- Crear archivo ---
m = re.match(r"(?i)^crea un archivo(?:\s+(\S+))?(?:\s+(.*))?$", texto, re.S)
if m:
nombre = limpiar(m.group(1) or "")
if not nombre:
nombre = datetime.now().strftime("archivo-%Y%m%d-%H%M%S")
contenido = m.group(2) or ""
ruta = BASE / f"{nombre}.txt"
if ruta.exists():
await update.message.reply_text(f"Ya existe: {ruta}")
return
ruta.write_text(contenido + "\n", encoding="utf-8")
await update.message.reply_text(f"Archivo creado: {ruta}")
return
await update.message.reply_text(
"Puedes escribir:\n"
"- crea una carpeta nombre\n"
"- crea un archivo nombre contenido\n"
"- ejecuta procesos (o: " + ", ".join(COMANDOS) + ")"
)
app = ApplicationBuilder().token(TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, manejar))
app.run_polling()
Paso 6: ponerlo en marcha
En el Terminal, dentro de la carpeta telegram, ejecuta (con tus datos):
bash
export TELEGRAM_TOKEN="NUMEROS:RESTO_DEL_TOKEN"
export TELEGRAM_USER_ID="tu_id"
python3 bot.py
Si no aparece ningún error, el bot está escuchando. Deja esa ventana del Terminal abierta.
Paso 7: probarlo desde el móvil
Abre tu bot en Telegram y prueba:
crea un archivo notas Comprar pan y leche
El bot responderá con la ruta, y en tu Mac tendrás un archivo notas.txt dentro de Documentos/telegram con ese texto.
crea una carpeta fotos
Crea la carpeta fotos en ese mismo lugar.
ejecuta procesos
Te devolverá los 20 procesos que más CPU usan, con su PID, el porcentaje de CPU y memoria, y el nombre.
Cómo funciona el formato de los archivos:
- La primera palabra después de “archivo” es el nombre (sin espacios; usa guiones:
lista-compra). - Todo lo que escribas después del nombre es el contenido, y puede tener varias líneas.
- Si solo escribes
crea un archivo, se crea uno con la fecha y la hora como nombre. - Siempre se crea como
.txt.
Añade tus propios comandos
Cada comando es una línea del diccionario COMANDOS: el nombre que tú escribes y el comando real, dividido en palabras separadas dentro de una lista. Por ejemplo, para consultar la red:
python
"red": ["ifconfig", "en0"],
Fíjate en que cada argumento va separado (["df", "-h"]) y no junto ("df -h"). Así el sistema trata cada parte como un dato y no como una instrucción.
Guarda el cambio, para el bot con Ctrl + C y vuelve a lanzarlo.
Errores frecuentes
InvalidToken/ “Not Found”: el token está incompleto o mal copiado. Cópialo entero desde BotFather, con los números y los dos puntos del principio.ImportError ... circular import: has llamado a tu scripttoken.py(o con otro nombre reservado). Renómbralo y borra la carpeta__pycache__.- El bot arranca pero no responde: revisa que
TELEGRAM_USER_IDsea tu ID correcto, porque el bot ignora a cualquier otra cuenta. - Los
exportdesaparecen: si cierras el Terminal, tienes que volver a escribirlos antes de lanzarpython3 bot.py. - El bot no reconoce un comando nuevo: no lo has reiniciado. Los cambios solo se aplican al volver a ejecutar
python3 bot.py. - “El comando tardó demasiado”: superó los 15 segundos. Evita comandos que se quedan ejecutándose, como
topsin opciones.
Buenas prácticas de seguridad
- Empieza solo con comandos de lectura (ver procesos, disco, fecha). Son inofensivos.
- Piensa dos veces antes de añadir comandos que modifiquen cosas como apagar, reiniciar o borrar. Si lo haces, añade una confirmación (por ejemplo, que el bot pida responder “sí” antes de ejecutar).
- Activa la verificación en dos pasos en Telegram. Tu cuenta es la única llave de acceso a tu Mac.
- No compartas tu token, ni en capturas ni en foros.
- Recuerda que el bot solo funciona mientras el Mac esté encendido y con el script ejecutándose.