vigilancia: panorama con autoborrado en Telegram a los 10min (proceso separado) - PANORAMA_DELETE_AFTER
This commit is contained in:
110
vigilancia/panorama.py
Normal file
110
vigilancia/panorama.py
Normal file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
import requests
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import config
|
||||
|
||||
# Segundos tras los que se borran las fotos del panorama en Telegram (default 10 min)
|
||||
DELETE_AFTER = int(os.getenv("PANORAMA_DELETE_AFTER", "600"))
|
||||
|
||||
if not config.CAMARAS:
|
||||
print("No hay cámaras configuradas")
|
||||
sys.exit(1)
|
||||
|
||||
def programar_borrado(message_ids):
|
||||
"""Borra los mensajes (fotos del panorama) tras DELETE_AFTER segundos.
|
||||
Se lanza en un proceso separado para que sobreviva al cierre de este script."""
|
||||
codigo = (
|
||||
"import time, requests\n"
|
||||
f"time.sleep({DELETE_AFTER})\n"
|
||||
f"chat={config.TELEGRAM_CHAT_ID!r}\n"
|
||||
f"ids={list(message_ids)!r}\n"
|
||||
f"tok={config.TELEGRAM_TOKEN!r}\n"
|
||||
"for mid in ids:\n"
|
||||
" try:\n"
|
||||
" requests.post('https://api.telegram.org/bot'+tok+'/deleteMessage',"
|
||||
" data={'chat_id': chat, 'message_id': mid}, timeout=10)\n"
|
||||
" print('borrado', mid)\n"
|
||||
" except Exception as e:\n"
|
||||
" print('err', mid, e)\n"
|
||||
)
|
||||
subprocess.Popen(["python3", "-c", codigo],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
start_new_session=True,
|
||||
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0))
|
||||
|
||||
def capturar_snapshot():
|
||||
os.makedirs(config.SNAPSHOT_DIR, exist_ok=True)
|
||||
resultados = []
|
||||
for cam in config.CAMARAS:
|
||||
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
ruta = os.path.join(config.SNAPSHOT_DIR, f"panorama_{cam['nombre']}_{ts}.jpg")
|
||||
cmd = ["ffmpeg", "-i", cam["rtsp"], "-frames:v", "1", "-q:v", "2",
|
||||
"-y", "-hide_banner", "-loglevel", "error", ruta]
|
||||
try:
|
||||
subprocess.run(cmd, timeout=15, check=True)
|
||||
print(f"[{cam['nombre']}] Snapshot: {ruta}")
|
||||
resultados.append((cam["nombre"], ruta))
|
||||
except Exception as e:
|
||||
print(f"[{cam['nombre']}] Error: {e}")
|
||||
return resultados
|
||||
|
||||
def enviar_album(fotos):
|
||||
if not fotos:
|
||||
print("No hay fotos para enviar")
|
||||
return
|
||||
if len(fotos) == 1:
|
||||
nombre, ruta = fotos[0]
|
||||
url = f"https://api.telegram.org/bot{config.TELEGRAM_TOKEN}/sendPhoto"
|
||||
try:
|
||||
with open(ruta, "rb") as f:
|
||||
r = requests.post(url,
|
||||
data={"chat_id": config.TELEGRAM_CHAT_ID,
|
||||
"caption": f"📷 {nombre} — {datetime.now().strftime('%H:%M:%S')}"},
|
||||
files={"photo": f}, timeout=30)
|
||||
print(f"Foto enviada: HTTP {r.status_code}")
|
||||
if r.status_code == 200:
|
||||
programar_borrado([r.json()["result"]["message_id"]])
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
else:
|
||||
url = f"https://api.telegram.org/bot{config.TELEGRAM_TOKEN}/sendMediaGroup"
|
||||
media = []
|
||||
files_dict = {}
|
||||
for i, (nombre, ruta) in enumerate(fotos):
|
||||
media.append({
|
||||
"type": "photo",
|
||||
"media": f"attach://{i}",
|
||||
"caption": f"📷 {nombre} — {datetime.now().strftime('%H:%M:%S')}"
|
||||
})
|
||||
files_dict[str(i)] = open(ruta, "rb")
|
||||
try:
|
||||
r = requests.post(url, data={"chat_id": config.TELEGRAM_CHAT_ID,
|
||||
"media": json.dumps(media)}, files=files_dict, timeout=30)
|
||||
print(f"Album enviado: HTTP {r.status_code}")
|
||||
if r.status_code == 200:
|
||||
ids = [m["message_id"] for m in r.json()["result"]]
|
||||
print(f"Borrado programado dentro de {DELETE_AFTER}s para {len(ids)} foto(s)")
|
||||
programar_borrado(ids)
|
||||
else:
|
||||
print(f"Error: {r.text[:300]}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
finally:
|
||||
for f in files_dict.values():
|
||||
f.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Capturando snapshots...")
|
||||
fotos = capturar_snapshot()
|
||||
if fotos:
|
||||
print(f"Enviando {len(fotos)} foto(s) a IDD...")
|
||||
enviar_album(fotos)
|
||||
else:
|
||||
print("No se capturaron fotos")
|
||||
Reference in New Issue
Block a user