commit 5c74e96b3a668840af991180ab12081ae791977f Author: Blake Date: Thu Jun 4 20:15:12 2026 -0500 pull diff --git a/.env b/.env new file mode 100644 index 0000000..23912aa --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +ADGUARD_HOST=http://192.168.1.235:30004 +ADGUARD_USER=bmartin +ADGUARD_PASS=C0n3k4!1585321 diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef8b20f --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# AdGuard Block Battle Rankings + +A Flask dashboard that pulls client block stats from AdGuard Home and displays +each client as a ranked anime-tier character card. + +## Tier System + +| Tier | Label | Block Range | Color | +|------|---------------|-------------|--------| +| 1 | Civilian | 0-50 | Green | +| 2 | Rookie | 51-200 | Yellow | +| 3 | Protagonist | 201-500 | Orange | +| 4 | Hardened Fighter | 501-1000 | Red | +| 5 | Final Boss | 1000+ | Purple | + +## Setup + +1. Install dependencies: + pip install -r requirements.txt + +2. Set environment variables (or edit app.py directly): + export ADGUARD_HOST=http://vpn.umbrellapants.xyz:3000 + export ADGUARD_USER=your_username + export ADGUARD_PASS=your_password + +3. Run: + python app.py + +4. Open http://localhost:5000 + +## Swapping in Character Art + +Each tier uses an SVG placeholder. To replace with real images: +- Add your images to static/characters/ named tier1.png through tier5.png +- In index.html, replace the charSVG() call in the card template with: + Tier ${client.tier} + +## Deployment with mod_wsgi + +Create a wsgi.py at the project root: + + from app import app as application + +Then point your Apache VirtualHost at wsgi.py. + +## Auto-refresh + +The dashboard polls AdGuard every 60 seconds automatically. +Adjust the interval at the bottom of index.html (setInterval line). diff --git a/app.py b/app.py new file mode 100644 index 0000000..44f9cdc --- /dev/null +++ b/app.py @@ -0,0 +1,12 @@ +from flask import Flask, render_template, request + +app = Flask(__name__) + +@app.route("/blocked") +def blocked(): + domain = request.args.get("domain", "that site") + reason = request.args.get("reason", "blocked by network policy") + return render_template("blocked.html", domain=domain, reason=reason) + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000, debug=True) diff --git a/dashboard.py b/dashboard.py new file mode 100644 index 0000000..a71bc74 --- /dev/null +++ b/dashboard.py @@ -0,0 +1,92 @@ +from flask import Flask, render_template, jsonify +import requests +import os +from requests.auth import HTTPBasicAuth +from dotenv import load_dotenv + +load_dotenv('/opt/adguard-dashboard/.env') + +app = Flask(__name__) + +ADGUARD_HOST = os.environ.get("ADGUARD_HOST") +ADGUARD_USER = os.environ.get("ADGUARD_USER") +ADGUARD_PASS = os.environ.get("ADGUARD_PASS") +EXCLUDE_CLIENTS = ["192.168.1.235"] + +def get_tier(count): + if count <= 500: + return {"tier": 1, "label": "Innocent", "desc": "Blissfully unaware", "color": "#4ade80"} + elif count <= 2000: + return {"tier": 2, "label": "Rookie", "desc": "Starting to notice things", "color": "#facc15"} + elif count <= 5000: + return {"tier": 3, "label": "Protagonist", "desc": "Things are getting real", "color": "#fb923c"} + elif count <= 9000: + return {"tier": 4, "label": "Hardened Fighter", "desc": "Seen some things", "color": "#f87171"} + else: + return {"tier": 5, "label": "Final Boss", "desc": "Pure chaos energy", "color": "#c084fc"} + + +def get_client_names(): + try: + resp = requests.get( + f"{ADGUARD_HOST}/control/clients", + auth=HTTPBasicAuth(ADGUARD_USER, ADGUARD_PASS), + timeout=5 + ) + resp.raise_for_status() + data = resp.json() + lookup = {} + for client in data.get("clients", []): + for ip in client.get("ids", []): + lookup[ip] = client["name"] + return lookup + except Exception: + return {} + + +@app.route("/") +def index(): + return render_template("dashboard.html") + + +@app.route("/api/clients") +def clients(): + try: + names = get_client_names() + + resp = requests.get( + f"{ADGUARD_HOST}/control/stats", + auth=HTTPBasicAuth(ADGUARD_USER, ADGUARD_PASS), + timeout=5 + ) + resp.raise_for_status() + data = resp.json() + + top_clients = data.get("top_clients", []) + + result = [] + for entry in top_clients: + for ip, count in entry.items(): + if ip in EXCLUDE_CLIENTS: + continue + tier_info = get_tier(count) + result.append({ + "name": names.get(ip, ip), + "ip": ip, + "blocks": count, + **tier_info + }) + + result.sort(key=lambda x: x["blocks"], reverse=True) + return jsonify({"clients": result, "error": None}) + + except requests.exceptions.ConnectionError: + return jsonify({"clients": [], "error": "Could not connect to AdGuard Home"}) + except requests.exceptions.Timeout: + return jsonify({"clients": [], "error": "AdGuard Home timed out"}) + except Exception as e: + return jsonify({"clients": [], "error": str(e)}) + + +if __name__ == "__main__": + app.run(debug=True, host="0.0.0.0", port=5001) diff --git a/dashboard.wsgi b/dashboard.wsgi new file mode 100644 index 0000000..864b671 --- /dev/null +++ b/dashboard.wsgi @@ -0,0 +1,3 @@ +import sys +sys.path.insert(0, '/opt/adguard-dashboard') +from dashboard import app as application diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..eab2b35 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +flask>=3.0.0 +requests>=2.31.0 diff --git a/static/characters/tier1_1.png b/static/characters/tier1_1.png new file mode 100644 index 0000000..7ead86a Binary files /dev/null and b/static/characters/tier1_1.png differ diff --git a/static/characters/tier1_2.png b/static/characters/tier1_2.png new file mode 100644 index 0000000..a0a6997 Binary files /dev/null and b/static/characters/tier1_2.png differ diff --git a/static/characters/tier1_3.png b/static/characters/tier1_3.png new file mode 100644 index 0000000..9e28c5f Binary files /dev/null and b/static/characters/tier1_3.png differ diff --git a/static/characters/tier1_4.png b/static/characters/tier1_4.png new file mode 100644 index 0000000..6ba8b6f Binary files /dev/null and b/static/characters/tier1_4.png differ diff --git a/static/characters/tier1_5.png b/static/characters/tier1_5.png new file mode 100644 index 0000000..2326194 Binary files /dev/null and b/static/characters/tier1_5.png differ diff --git a/static/characters/tier2_1.png b/static/characters/tier2_1.png new file mode 100644 index 0000000..2df8277 Binary files /dev/null and b/static/characters/tier2_1.png differ diff --git a/static/characters/tier2_2.png b/static/characters/tier2_2.png new file mode 100644 index 0000000..aea03d4 Binary files /dev/null and b/static/characters/tier2_2.png differ diff --git a/static/characters/tier2_3.png b/static/characters/tier2_3.png new file mode 100644 index 0000000..a948677 Binary files /dev/null and b/static/characters/tier2_3.png differ diff --git a/static/characters/tier2_4.png b/static/characters/tier2_4.png new file mode 100644 index 0000000..f0d9d59 Binary files /dev/null and b/static/characters/tier2_4.png differ diff --git a/static/characters/tier2_5.png b/static/characters/tier2_5.png new file mode 100644 index 0000000..46ddaff Binary files /dev/null and b/static/characters/tier2_5.png differ diff --git a/static/characters/tier3_1.png b/static/characters/tier3_1.png new file mode 100644 index 0000000..b751097 Binary files /dev/null and b/static/characters/tier3_1.png differ diff --git a/static/characters/tier3_2.png b/static/characters/tier3_2.png new file mode 100644 index 0000000..9ce06b6 Binary files /dev/null and b/static/characters/tier3_2.png differ diff --git a/static/characters/tier3_3.png b/static/characters/tier3_3.png new file mode 100644 index 0000000..d30e32f Binary files /dev/null and b/static/characters/tier3_3.png differ diff --git a/static/characters/tier3_4.png b/static/characters/tier3_4.png new file mode 100644 index 0000000..e6af606 Binary files /dev/null and b/static/characters/tier3_4.png differ diff --git a/static/characters/tier3_5.png b/static/characters/tier3_5.png new file mode 100644 index 0000000..3b58c12 Binary files /dev/null and b/static/characters/tier3_5.png differ diff --git a/static/characters/tier4_1.png b/static/characters/tier4_1.png new file mode 100644 index 0000000..c6cdea8 Binary files /dev/null and b/static/characters/tier4_1.png differ diff --git a/static/characters/tier4_2.png b/static/characters/tier4_2.png new file mode 100644 index 0000000..f7391b3 Binary files /dev/null and b/static/characters/tier4_2.png differ diff --git a/static/characters/tier4_3.png b/static/characters/tier4_3.png new file mode 100644 index 0000000..4b41031 Binary files /dev/null and b/static/characters/tier4_3.png differ diff --git a/static/characters/tier4_4.png b/static/characters/tier4_4.png new file mode 100644 index 0000000..b03bccf Binary files /dev/null and b/static/characters/tier4_4.png differ diff --git a/static/characters/tier4_5.png b/static/characters/tier4_5.png new file mode 100644 index 0000000..088d8b7 Binary files /dev/null and b/static/characters/tier4_5.png differ diff --git a/static/characters/tier5_1.png b/static/characters/tier5_1.png new file mode 100644 index 0000000..3b73222 Binary files /dev/null and b/static/characters/tier5_1.png differ diff --git a/static/characters/tier5_2.png b/static/characters/tier5_2.png new file mode 100644 index 0000000..ba54046 Binary files /dev/null and b/static/characters/tier5_2.png differ diff --git a/static/characters/tier5_3.png b/static/characters/tier5_3.png new file mode 100644 index 0000000..9e77448 Binary files /dev/null and b/static/characters/tier5_3.png differ diff --git a/static/characters/tier5_4.png b/static/characters/tier5_4.png new file mode 100644 index 0000000..1e0e104 Binary files /dev/null and b/static/characters/tier5_4.png differ diff --git a/static/characters/tier5_5.png b/static/characters/tier5_5.png new file mode 100644 index 0000000..51ffea2 Binary files /dev/null and b/static/characters/tier5_5.png differ diff --git a/templates/dashboard.html b/templates/dashboard.html new file mode 100644 index 0000000..9e5a4f0 --- /dev/null +++ b/templates/dashboard.html @@ -0,0 +1,520 @@ + + + + + + AdGuard Block Tracker + + + + + +
+

Block Battle Rankings

+
AdGuard Home — Network Threat Index
+
+ +
+   Connecting... + + +
+ +
+ T1 Innocent 0-500 + T2 Rookie 51-2000 + T3 Protagonist 2001-5000 + T4 Fighter 5001-9000 + T5 Final Boss Over 9000! +
+ +
+ + + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..12be8be --- /dev/null +++ b/templates/index.html @@ -0,0 +1,506 @@ + + + + + + AdGuard Block Tracker + + + + + +
+

Block Battle Rankings

+
AdGuard Home — Network Threat Index
+
+ +
+   Connecting... + + +
+ +
+ T1 Civilian 0-50 + T2 Rookie 51-200 + T3 Protagonist 201-500 + T4 Fighter 501-1000 + T5 Final Boss 1000+ +
+ +
+ + + +