05-sep: [feat] salir de sesion (/salir), repo por defecto (/defecto) y limpiar pantalla (/limpiar) en ambos bots
This commit is contained in:
@@ -154,6 +154,7 @@ def teclado_sistema():
|
|||||||
_btn("📸 Panorama", PREFIJO + "acc:panorama"),
|
_btn("📸 Panorama", PREFIJO + "acc:panorama"),
|
||||||
_btn("🧹 Limpieza", PREFIJO + "acc:limpieza"),
|
_btn("🧹 Limpieza", PREFIJO + "acc:limpieza"),
|
||||||
],
|
],
|
||||||
|
[_btn("🗑️ Limpiar pantalla", PREFIJO + "acc:limpiar")],
|
||||||
FILA_VOLVER,
|
FILA_VOLVER,
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -399,6 +400,7 @@ def _ejecutar_accion(chat_id, message_id, partes):
|
|||||||
"temperatura": "temperatura",
|
"temperatura": "temperatura",
|
||||||
"panorama": "panorama",
|
"panorama": "panorama",
|
||||||
"limpieza": "limpieza",
|
"limpieza": "limpieza",
|
||||||
|
"limpiar": "limpiar",
|
||||||
"aimesh": "aiMesh estado",
|
"aimesh": "aiMesh estado",
|
||||||
"qos": "qos estado",
|
"qos": "qos estado",
|
||||||
"limite": "limite listar",
|
"limite": "limite listar",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ panel_descargas = {} # chat_id -> estado del panel editable
|
|||||||
temporizadores_parental = {} # alias normalizado -> Timer de desbloqueo
|
temporizadores_parental = {} # alias normalizado -> Timer de desbloqueo
|
||||||
menu_pendiente = {} # chat_id -> accion de texto libre esperada (menu botones)
|
menu_pendiente = {} # chat_id -> accion de texto libre esperada (menu botones)
|
||||||
menu_pausa_nombre = {} # chat_id -> nombre elegido en flujo de pausa
|
menu_pausa_nombre = {} # chat_id -> nombre elegido en flujo de pausa
|
||||||
|
historial_chat = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
|
||||||
|
|
||||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||||
LOG = os.path.join(BASE, "bot.log")
|
LOG = os.path.join(BASE, "bot.log")
|
||||||
@@ -98,6 +99,10 @@ def enviar(texto, chat_id):
|
|||||||
d = r.json()
|
d = r.json()
|
||||||
if d.get("ok"):
|
if d.get("ok"):
|
||||||
ultimo_id = d["result"].get("message_id")
|
ultimo_id = d["result"].get("message_id")
|
||||||
|
lista = historial_chat.setdefault(chat_id, [])
|
||||||
|
lista.append(ultimo_id)
|
||||||
|
if len(lista) > 300:
|
||||||
|
historial_chat[chat_id] = lista[-300:]
|
||||||
else:
|
else:
|
||||||
log(f"Telegram sendMessage error: {d.get('description', d)}")
|
log(f"Telegram sendMessage error: {d.get('description', d)}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -267,6 +272,26 @@ def borrar(chat_id, message_id):
|
|||||||
print("Error borrando:", e)
|
print("Error borrando:", e)
|
||||||
|
|
||||||
|
|
||||||
|
def limpiar_pantalla(chat_id):
|
||||||
|
"""Borra los mensajes que el bot ha enviado en este chat (/limpiar)."""
|
||||||
|
lista = historial_chat.pop(chat_id, None) or []
|
||||||
|
borrados = 0
|
||||||
|
for mid in reversed(lista):
|
||||||
|
try:
|
||||||
|
r = requests.post(
|
||||||
|
f"https://api.telegram.org/bot{TOKEN}/deleteMessage",
|
||||||
|
data={"chat_id": chat_id, "message_id": mid},
|
||||||
|
timeout=8,
|
||||||
|
)
|
||||||
|
if r.json().get("ok"):
|
||||||
|
borrados += 1
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
aviso = enviar(f"🧹 Pantalla limpia ({borrados} mensajes borrados).", chat_id)
|
||||||
|
if aviso:
|
||||||
|
threading.Timer(6.0, borrar, args=(chat_id, aviso)).start()
|
||||||
|
|
||||||
|
|
||||||
def mandar_tv(mensaje, simple):
|
def mandar_tv(mensaje, simple):
|
||||||
try:
|
try:
|
||||||
url = f"{TV_API}?texto={urllib.parse.quote(mensaje)}"
|
url = f"{TV_API}?texto={urllib.parse.quote(mensaje)}"
|
||||||
@@ -374,8 +399,9 @@ def procesar(texto, chat_id):
|
|||||||
log(f"panorama: {r.stdout.strip()[-200:]}")
|
log(f"panorama: {r.stdout.strip()[-200:]}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"panorama error: {e}")
|
log(f"panorama error: {e}")
|
||||||
elif t in ("limpieza", "/limpieza", "limpiar", "/limpiar"):
|
elif t in ("limpieza", "/limpieza", "limpiar", "/limpiar", "clear", "/clear"):
|
||||||
enviar("🧹 Ejecutando limpieza...", chat_id)
|
if t in ("limpieza", "/limpieza"):
|
||||||
|
enviar("🧹 Ejecutando limpieza de procesos...", chat_id)
|
||||||
try:
|
try:
|
||||||
from limpiar import limpiar
|
from limpiar import limpiar
|
||||||
resultado = limpiar()
|
resultado = limpiar()
|
||||||
@@ -383,6 +409,8 @@ def procesar(texto, chat_id):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"limpieza error: {e}")
|
log(f"limpieza error: {e}")
|
||||||
enviar(f"❌ Error: {e}", chat_id)
|
enviar(f"❌ Error: {e}", chat_id)
|
||||||
|
else:
|
||||||
|
limpiar_pantalla(chat_id)
|
||||||
elif t.startswith("youtube ") or t.startswith("/youtube "):
|
elif t.startswith("youtube ") or t.startswith("/youtube "):
|
||||||
url = texto.split(" ", 1)[1].strip()
|
url = texto.split(" ", 1)[1].strip()
|
||||||
if not url:
|
if not url:
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ AUTH = (OC_USER, OC_PASS)
|
|||||||
bloqueos = {} # chat_id -> True (procesando mensaje)
|
bloqueos = {} # chat_id -> True (procesando mensaje)
|
||||||
sesiones = {} # chat_id -> {'repo': slug, 'session': id, 'model': obj|None}
|
sesiones = {} # chat_id -> {'repo': slug, 'session': id, 'model': obj|None}
|
||||||
repos_cache = [] # lista de {'slug','dir'}
|
repos_cache = [] # lista de {'slug','dir'}
|
||||||
|
sentidos = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
|
||||||
|
|
||||||
|
|
||||||
def log(linea):
|
def log(linea):
|
||||||
@@ -101,10 +102,24 @@ def tg(method, data=None, files=None):
|
|||||||
return {"ok": False}
|
return {"ok": False}
|
||||||
|
|
||||||
|
|
||||||
|
def _registrar(chat_id, respuesta):
|
||||||
|
try:
|
||||||
|
if respuesta and respuesta.get("ok"):
|
||||||
|
mid = (respuesta.get("result") or {}).get("message_id")
|
||||||
|
if mid:
|
||||||
|
lista = sentidos.setdefault(str(chat_id), [])
|
||||||
|
lista.append(mid)
|
||||||
|
if len(lista) > 300:
|
||||||
|
sentidos[str(chat_id)] = lista[-300:]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def enviar(chat_id, texto, parse="HTML"):
|
def enviar(chat_id, texto, parse="HTML"):
|
||||||
for i in range(0, len(texto), 3900):
|
for i in range(0, len(texto), 3900):
|
||||||
tg("sendMessage", {"chat_id": chat_id, "text": texto[i:i + 3900],
|
_registrar(chat_id, tg("sendMessage",
|
||||||
"parse_mode": parse})
|
{"chat_id": chat_id, "text": texto[i:i + 3900],
|
||||||
|
"parse_mode": parse}))
|
||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
|
||||||
@@ -113,8 +128,9 @@ def enviar_doc(chat_id, ruta, caption=None):
|
|||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
with open(ruta, "rb") as f:
|
with open(ruta, "rb") as f:
|
||||||
tg("sendDocument", {"chat_id": chat_id, "caption": caption},
|
_registrar(chat_id, tg("sendDocument",
|
||||||
{"document": (os.path.basename(ruta), f)})
|
{"chat_id": chat_id, "caption": caption},
|
||||||
|
{"document": (os.path.basename(ruta), f)}))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"doc error {ruta}: {e}")
|
log(f"doc error {ruta}: {e}")
|
||||||
|
|
||||||
@@ -124,8 +140,10 @@ def teclado(filas):
|
|||||||
|
|
||||||
|
|
||||||
def tg_con_teclado(chat_id, texto, filas):
|
def tg_con_teclado(chat_id, texto, filas):
|
||||||
tg("sendMessage", {"chat_id": chat_id, "text": texto, "parse_mode": "HTML",
|
_registrar(chat_id, tg("sendMessage",
|
||||||
"reply_markup": json.dumps(teclado(filas))})
|
{"chat_id": chat_id, "text": texto,
|
||||||
|
"parse_mode": "HTML",
|
||||||
|
"reply_markup": json.dumps(teclado(filas))}))
|
||||||
|
|
||||||
|
|
||||||
def editar(chat_id, mid, texto, filas=None):
|
def editar(chat_id, mid, texto, filas=None):
|
||||||
@@ -425,9 +443,11 @@ def cmd_ayuda(chat):
|
|||||||
"<b>🤖 OpenCode por Telegram</b>\n"
|
"<b>🤖 OpenCode por Telegram</b>\n"
|
||||||
"Escribe cualquier cosa y lo hará el agente en el repo activo.\n\n"
|
"Escribe cualquier cosa y lo hará el agente en el repo activo.\n\n"
|
||||||
"<b>Comandos:</b>\n"
|
"<b>Comandos:</b>\n"
|
||||||
"<code>/nueva [texto]</code> — nueva sesión (borra contexto)\n"
|
"<code>/nueva [texto]</code> — sesión nueva (olvida el contexto)\n"
|
||||||
"<code>/proyecto</code> — elegir repo de trabajo\n"
|
"<code>/salir</code> — cerrar la sesión actual (la próxima arranca limpia)\n"
|
||||||
|
"<code>/proyecto</code> / <code>/defecto</code> — elegir repo (queda por defecto)\n"
|
||||||
"<code>/modelo</code> — elegir modelo\n"
|
"<code>/modelo</code> — elegir modelo\n"
|
||||||
|
"<code>/limpiar</code> — limpiar la pantalla (borra mensajes del bot)\n"
|
||||||
"<code>/estado</code> — repo y modelo actuales\n"
|
"<code>/estado</code> — repo y modelo actuales\n"
|
||||||
"<code>/ayuda</code> — esta ayuda\n\n"
|
"<code>/ayuda</code> — esta ayuda\n\n"
|
||||||
"Los ficheros que cree te llegarán como documentos."
|
"Los ficheros que cree te llegarán como documentos."
|
||||||
@@ -463,6 +483,56 @@ def cmd_nueva(chat, resto):
|
|||||||
enviar(chat, "🧠 Sesión nueva creada. Dime qué hago.")
|
enviar(chat, "🧠 Sesión nueva creada. Dime qué hago.")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_salir(chat):
|
||||||
|
"""Sale de la sesion actual: la cierra y avisa que la proxima sera nueva."""
|
||||||
|
st = sesiones.get(str(chat))
|
||||||
|
if st and st.get("session"):
|
||||||
|
try:
|
||||||
|
oc_post(f"/session/{st['session']}/abort", {})
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
sid, _ = crear_sesion()
|
||||||
|
slug, _ = repo_activo()
|
||||||
|
st["session"] = sid
|
||||||
|
sesiones[str(chat)] = st
|
||||||
|
guardar_estado()
|
||||||
|
enviar(chat, "🚪 Sesión anterior cerrada. La próxima petición arranca "
|
||||||
|
"en una sesión nueva sin contexto.")
|
||||||
|
else:
|
||||||
|
enviar(chat, "No había ninguna sesión abierta.")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_limpiar(chat):
|
||||||
|
"""Borra los mensajes que el bot ha enviado en este chat."""
|
||||||
|
lista = sentidos.get(str(chat)) or []
|
||||||
|
borrados = 0
|
||||||
|
for mid in reversed(lista):
|
||||||
|
try:
|
||||||
|
r = requests.post(f"{API}/deleteMessage",
|
||||||
|
data={"chat_id": chat, "message_id": mid},
|
||||||
|
timeout=15)
|
||||||
|
if r.json().get("ok"):
|
||||||
|
borrados += 1
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
sentidos[str(chat)] = []
|
||||||
|
enviar(chat, f"🧹 Pantalla limpia ({borrados} mensajes borrados).")
|
||||||
|
# borra tambien este aviso al cabo de unos segundos
|
||||||
|
threading.Timer(6.0, _autolimpia, args=(chat,)).start()
|
||||||
|
|
||||||
|
|
||||||
|
def _autolimpia(chat):
|
||||||
|
lista = sentidos.get(str(chat)) or []
|
||||||
|
for mid in reversed(lista[:1]):
|
||||||
|
try:
|
||||||
|
requests.post(f"{API}/deleteMessage",
|
||||||
|
data={"chat_id": chat, "message_id": mid},
|
||||||
|
timeout=10)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
sentidos[str(chat)] = [m for m in lista if m != mid]
|
||||||
|
|
||||||
|
|
||||||
def cmd_proyecto(chat):
|
def cmd_proyecto(chat):
|
||||||
lista = listar_repos()
|
lista = listar_repos()
|
||||||
if not lista:
|
if not lista:
|
||||||
@@ -474,7 +544,8 @@ def cmd_proyecto(chat):
|
|||||||
marca = " ✅" if r["slug"] == slug_act else ""
|
marca = " ✅" if r["slug"] == slug_act else ""
|
||||||
filas.append([{"text": r["slug"] + marca,
|
filas.append([{"text": r["slug"] + marca,
|
||||||
"callback_data": f"cb:repo:{i}"}])
|
"callback_data": f"cb:repo:{i}"}])
|
||||||
tg_con_teclado(chat, "📂 Elige repo de trabajo:", filas)
|
tg_con_teclado(chat, "📂 Elige repo de trabajo. Quedará fijado como "
|
||||||
|
"repo por defecto del bot (reinicia el serve):", filas)
|
||||||
|
|
||||||
|
|
||||||
def cmd_modelo(chat):
|
def cmd_modelo(chat):
|
||||||
@@ -556,7 +627,11 @@ def procesar(texto, chat):
|
|||||||
cmd_ayuda(chat)
|
cmd_ayuda(chat)
|
||||||
elif comando in ("/nueva", "/nuevo"):
|
elif comando in ("/nueva", "/nuevo"):
|
||||||
cmd_nueva(chat, resto)
|
cmd_nueva(chat, resto)
|
||||||
elif comando in ("/proyecto", "/repo"):
|
elif comando in ("/salir", "/fin", "/exit"):
|
||||||
|
cmd_salir(chat)
|
||||||
|
elif comando in ("/limpiar", "/clear"):
|
||||||
|
cmd_limpiar(chat)
|
||||||
|
elif comando in ("/proyecto", "/repo", "/defecto"):
|
||||||
cmd_proyecto(chat)
|
cmd_proyecto(chat)
|
||||||
elif comando == "/modelo":
|
elif comando == "/modelo":
|
||||||
cmd_modelo(chat)
|
cmd_modelo(chat)
|
||||||
|
|||||||
Reference in New Issue
Block a user