diff --git a/ui/cloudflare.py b/ui/cloudflare.py
index eb01187..9149e05 100644
--- a/ui/cloudflare.py
+++ b/ui/cloudflare.py
@@ -1,42 +1,103 @@
import os
import requests
+from datetime import datetime
-CF_API_TOKEN = os.getenv("CF_API_TOKEN")
-ZONE = os.getenv("CF_ZONE")
-SUBDOMAINS = os.getenv("CF_SUBDOMAINS").split(",")
+# ----------------------------
+# Config da .env
+# ----------------------------
+CF_API_TOKEN = os.getenv("CF_UI_API_TOKEN")
+CF_ZONE = os.getenv("CF_ZONE")
+CF_SUBDOMAINS = os.getenv("CF_UI_SUBDOMAINS", "").split(",")
+PUBLIC_IP_API = os.getenv("PUBLIC_IP_API", "https://api.ipify.org") # opzionale
HEADERS = {
"Authorization": f"Bearer {CF_API_TOKEN}",
"Content-Type": "application/json"
}
+# ----------------------------
+# Funzioni
+# ----------------------------
def get_public_ip():
- return requests.get("https://api.ipify.org", timeout=5).text.strip()
+ """Recupera l'IP pubblico"""
+ try:
+ ip = requests.get(PUBLIC_IP_API, timeout=5).text.strip()
+ return ip
+ except Exception:
+ return "N/A"
-def get_dns_status():
- ip_pubblico = get_public_ip()
- out = []
-
- zone = requests.get(
- "https://api.cloudflare.com/client/v4/zones",
- headers=HEADERS,
- params={"name": ZONE}
- ).json()["result"][0]
-
- for sub in SUBDOMAINS:
- fqdn = f"{sub}.{ZONE}"
- dns = requests.get(
- f"https://api.cloudflare.com/client/v4/zones/{zone['id']}/dns_records",
+def get_zone_id():
+ """Recupera l'ID della zona Cloudflare"""
+ try:
+ resp = requests.get(
+ "https://api.cloudflare.com/client/v4/zones",
headers=HEADERS,
- params={"name": fqdn}
- ).json()["result"][0]
+ params={"name": CF_ZONE}
+ ).json()
+ if resp["success"] and resp["result"]:
+ return resp["result"][0]["id"]
+ else:
+ raise Exception(f"Zona '{CF_ZONE}' non trovata o errore API.")
+ except Exception as e:
+ print(f"[ERROR] get_zone_id: {e}")
+ return None
- out.append({
- "name": fqdn,
- "dns_ip": dns["content"],
- "public_ip": ip_pubblico,
- "proxied": dns["proxied"],
- "status": "OK" if dns["content"] == ip_pubblico else "MISMATCH"
- })
+def get_dns_records():
+ """Recupera i record DNS dei sottodomini"""
+ zone_id = get_zone_id()
+ if not zone_id:
+ return []
- return out
+ public_ip = get_public_ip()
+ records = []
+
+ for sub in CF_SUBDOMAINS:
+ fqdn = f"{sub}.{CF_ZONE}"
+ try:
+ resp = requests.get(
+ f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records",
+ headers=HEADERS,
+ params={"name": fqdn}
+ ).json()
+
+ if not resp["success"] or not resp["result"]:
+ # Record non trovato
+ records.append({
+ "name": fqdn,
+ "dns_ip": "N/A",
+ "public_ip": public_ip,
+ "proxied": False,
+ "status": "MISSING",
+ "last_updated": datetime.utcnow().isoformat()
+ })
+ continue
+
+ dns = resp["result"][0]
+ records.append({
+ "name": fqdn,
+ "dns_ip": dns["content"],
+ "public_ip": public_ip,
+ "proxied": dns["proxied"],
+ "status": "OK" if dns["content"] == public_ip else "MISMATCH",
+ "last_updated": dns.get("modified_on", datetime.utcnow().isoformat())
+ })
+
+ except Exception as e:
+ print(f"[ERROR] get_dns_records ({fqdn}): {e}")
+ records.append({
+ "name": fqdn,
+ "dns_ip": "ERROR",
+ "public_ip": public_ip,
+ "proxied": False,
+ "status": "ERROR",
+ "last_updated": datetime.utcnow().isoformat()
+ })
+
+ return records
+
+# ----------------------------
+# Test rapido
+# ----------------------------
+if __name__ == "__main__":
+ from pprint import pprint
+ pprint(get_dns_records())
diff --git a/ui/templates/index.html b/ui/templates/index.html
index 5093b20..42f58f7 100644
--- a/ui/templates/index.html
+++ b/ui/templates/index.html
@@ -1,42 +1,137 @@
-
+
-
- Cloudflare DDNS Status
-
-
+
+Cloudflare DDNS Status
+
+
-Cloudflare DDNS – Stato DNS
+Cloudflare DDNS – Stato DNS
-
-
- | Record |
- DNS IP |
- IP Pubblico |
- Proxy |
- Stato |
-
+
+
+
+
+ | Record |
+ DNS IP |
+ IP Pubblico |
+ Proxy |
+ Stato |
+ Ultimo aggiornamento |
+
+
+
+ {% for r in records %}
+
+ | {{ r.name }} |
+ {{ r.dns_ip }} |
+ {{ r.public_ip }} |
+ {{ "ON" if r.proxied else "OFF" }} |
+ {{ r.status }} |
+ {{ r.last_updated_human }} |
+
+ {% endfor %}
+
+
+
-{% for r in records %}
-
- | {{ r.name }} |
- {{ r.dns_ip }} |
- {{ r.public_ip }} |
- {{ "ON" if r.proxied else "OFF" }} |
-
- {{ r.status }}
- |
-
-{% endfor %}
-
+
+
+