05-sep: [feat] salir de sesion (/salir), repo por defecto (/defecto) y limpiar pantalla (/limpiar) en ambos bots

This commit is contained in:
juanjo
2026-09-05 22:39:57 +02:00
parent f78e1b1a98
commit 1c6bd113fd
3 changed files with 124 additions and 19 deletions

View File

@@ -52,6 +52,7 @@ AUTH = (OC_USER, OC_PASS)
bloqueos = {} # chat_id -> True (procesando mensaje)
sesiones = {} # chat_id -> {'repo': slug, 'session': id, 'model': obj|None}
repos_cache = [] # lista de {'slug','dir'}
sentidos = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
def log(linea):
@@ -101,10 +102,24 @@ def tg(method, data=None, files=None):
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"):
for i in range(0, len(texto), 3900):
tg("sendMessage", {"chat_id": chat_id, "text": texto[i:i + 3900],
"parse_mode": parse})
_registrar(chat_id, tg("sendMessage",
{"chat_id": chat_id, "text": texto[i:i + 3900],
"parse_mode": parse}))
time.sleep(0.3)
@@ -113,8 +128,9 @@ def enviar_doc(chat_id, ruta, caption=None):
return
try:
with open(ruta, "rb") as f:
tg("sendDocument", {"chat_id": chat_id, "caption": caption},
{"document": (os.path.basename(ruta), f)})
_registrar(chat_id, tg("sendDocument",
{"chat_id": chat_id, "caption": caption},
{"document": (os.path.basename(ruta), f)}))
except Exception as e:
log(f"doc error {ruta}: {e}")
@@ -124,8 +140,10 @@ def teclado(filas):
def tg_con_teclado(chat_id, texto, filas):
tg("sendMessage", {"chat_id": chat_id, "text": texto, "parse_mode": "HTML",
"reply_markup": json.dumps(teclado(filas))})
_registrar(chat_id, tg("sendMessage",
{"chat_id": chat_id, "text": texto,
"parse_mode": "HTML",
"reply_markup": json.dumps(teclado(filas))}))
def editar(chat_id, mid, texto, filas=None):
@@ -425,9 +443,11 @@ def cmd_ayuda(chat):
"<b>🤖 OpenCode por Telegram</b>\n"
"Escribe cualquier cosa y lo hará el agente en el repo activo.\n\n"
"<b>Comandos:</b>\n"
"<code>/nueva [texto]</code> — nueva sesión (borra contexto)\n"
"<code>/proyecto</code> — elegir repo de trabajo\n"
"<code>/nueva [texto]</code> — sesión nueva (olvida el contexto)\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>/limpiar</code> — limpiar la pantalla (borra mensajes del bot)\n"
"<code>/estado</code> — repo y modelo actuales\n"
"<code>/ayuda</code> — esta ayuda\n\n"
"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.")
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):
lista = listar_repos()
if not lista:
@@ -474,7 +544,8 @@ def cmd_proyecto(chat):
marca = " ✅" if r["slug"] == slug_act else ""
filas.append([{"text": r["slug"] + marca,
"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):
@@ -556,7 +627,11 @@ def procesar(texto, chat):
cmd_ayuda(chat)
elif comando in ("/nueva", "/nuevo"):
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)
elif comando == "/modelo":
cmd_modelo(chat)