diff --git a/services/telegram-bot/civil_protection.py b/services/telegram-bot/civil_protection.py new file mode 100644 index 0000000..9b200cc --- /dev/null +++ b/services/telegram-bot/civil_protection.py @@ -0,0 +1,151 @@ +import requests +import json +import os +import time +import datetime +from zoneinfo import ZoneInfo + +# --- CONFIGURAZIONE UTENTE --- +# πŸ‘‡πŸ‘‡ INSERISCI QUI I TUOI DATI πŸ‘‡πŸ‘‡ +TELEGRAM_BOT_TOKEN = "8155587974:AAF9OekvBpixtk8ZH6KoIc0L8edbhdXt7A4" +TELEGRAM_CHAT_IDS = ["64463169", "24827341", "132455422", "5405962012"] + +# --- ZONE DA MONITORARE --- +# EMR-B2 = Costa Romagnola (Rimini/Dogana) +# EMR-A2 = Alta Collina Romagnola (San Marino/Titano) +# EMR-D1 = Pianura Bolognese (Bologna CittΓ ) +TARGET_ZONES = ["EMR-B2", "EMR-A2", "EMR-D1"] + +# URL Ufficiale DPC +DPC_URL = "https://raw.githubusercontent.com/pcm-dpc/DPC-Bollettini-Criticita-Idrogeologica-Idraulica/master/files/geojson/today.json" + +# File di stato +STATE_FILE = "/home/daniely/docker/telegram-bot/dpc_state.json" + +# Mappe +RISK_MAP = { + 1: "🟑 GIALLA", + 2: "🟠 ARANCIONE", + 3: "πŸ”΄ ROSSA" +} + +RISK_TYPES = { + "idro": "πŸ’§ Idraulico", + "idrogeo": "⛰️ Idrogeologico", + "temporali": "⚑ Temporali", + "vento": "πŸ’¨ Vento", + "neve": "❄️ Neve", + "ghiaccio": "🧊 Ghiaccio", + "mare": "🌊 Mareggiate" +} + +def get_zone_label(zone_id): + if zone_id == "EMR-B2": return "Rimini / Bassa RSM" + if zone_id == "EMR-A2": return "Alta RSM / Carpegna" + if zone_id == "EMR-D1": return "Bologna CittΓ " + return zone_id + +def send_telegram_message(message): + if not TELEGRAM_BOT_TOKEN or "INSERISCI" in TELEGRAM_BOT_TOKEN: + print(f"[TEST OUT] {message}") + return + + url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage" + for chat_id in TELEGRAM_CHAT_IDS: + try: + requests.post(url, json={"chat_id": chat_id, "text": message, "parse_mode": "Markdown"}, timeout=10) + time.sleep(0.2) + except: pass + +def load_last_alert(): + if os.path.exists(STATE_FILE): + try: + with open(STATE_FILE, 'r') as f: return json.load(f) + except: pass + return {} + +def save_current_alert(data): + try: + with open(STATE_FILE, 'w') as f: json.dump(data, f) + except: pass + +def analyze_dpc(): + print("--- Controllo Protezione Civile ---") + + try: + r = requests.get(DPC_URL, timeout=10) + r.raise_for_status() + data = r.json() + except Exception as e: + print(f"Errore DPC: {e}") + return + + today_str = datetime.datetime.now(ZoneInfo("Europe/Rome")).strftime('%d/%m/%Y') + + active_alerts = {} + max_global_level = 0 + + # Stringa univoca per identificare se l'allerta Γ¨ cambiata nel contenuto + current_alert_signature = "" + + for feature in data['features']: + props = feature['properties'] + zone_id = props.get('zone_id') + + if zone_id in TARGET_ZONES: + zone_risks = [] + + for key, label in RISK_TYPES.items(): + level = props.get(f"crit_{key}") + + if level and level > 0: + if level > max_global_level: max_global_level = level + + color_icon = "🟑" if level == 1 else "🟠" if level == 2 else "πŸ”΄" + risk_str = f"{color_icon} {label}" + zone_risks.append(risk_str) + + if zone_risks: + label = get_zone_label(zone_id) + active_alerts[label] = zone_risks + # Aggiungiamo alla firma per capire se qualcosa Γ¨ cambiato + current_alert_signature += f"{zone_id}:{','.join(zone_risks)}|" + + # --- LOGICA DI INVIO --- + + last_state = load_last_alert() + last_date = last_state.get("date") + last_sig = last_state.get("signature", "") + + # Se tutto verde (livello 0) + if max_global_level == 0: + print("Nessuna allerta.") + if last_date == today_str and last_sig != "": + # Opzionale: Potremmo mandare "Allerta Rientrata", ma DPC resetta a mezzanotte. + # Per ora resettiamo solo lo stato. + save_current_alert({"date": today_str, "level": 0, "signature": ""}) + return + + # Invia SE: + # 1. È un giorno nuovo + # 2. OPPURE la situazione Γ¨ cambiata (es. aggiunto Bologna, o passato da Giallo a Rosso) + if last_date != today_str or current_alert_signature != last_sig: + + msg = f"πŸ“’ **PROTEZIONE CIVILE (Allerta)**\n" + msg += f"πŸ“… {today_str}\n\n" + + for zone_name, risks in active_alerts.items(): + msg += f"πŸ“ **{zone_name}**\n" + msg += "\n".join(risks) + "\n\n" + + msg += "_Fonte: Dipartimento Protezione Civile_" + + send_telegram_message(msg) + print("Allerta inviata.") + + save_current_alert({"date": today_str, "level": max_global_level, "signature": current_alert_signature}) + else: + print("Allerta giΓ  notificata e invariata.") + +if __name__ == "__main__": + analyze_dpc()