some changes

This commit is contained in:
pika 2025-03-10 19:16:26 +01:00
parent aff563a939
commit d8f3ce4fa3
3 changed files with 74 additions and 37 deletions

18
app.py
View file

@ -1,11 +1,11 @@
from flask import Flask, render_template, request, jsonify from flask import Flask, render_template, request, jsonify
import requests
import threading import threading
app = Flask(__name__) app = Flask(__name__)
# Speicher für Proxy-Subdomains (dict mit Liste für jeden Server)
proxy_data = {} proxy_data = {}
deleted_servers = set() # Hier speichern wir temporär gelöschte Server deleted_servers = set()
@app.route('/') @app.route('/')
def index(): def index():
@ -14,15 +14,13 @@ def index():
@app.route('/update', methods=['POST']) @app.route('/update', methods=['POST'])
def update(): def update():
"""Empfängt Subdomain-Daten von Caddy-Proxies"""
data = request.json data = request.json
if not data or "server" not in data or "entries" not in data: if not data or "server" not in data or "entries" not in data:
return jsonify({"error": "Invalid data"}), 400 return jsonify({"error": "Invalid data"}), 400
server_name = data["server"] server_name = data["server"]
proxy_data[server_name] = data["entries"] proxy_data[server_name] = data["entries"]
# Falls der Server wieder Daten sendet, entfernen wir ihn aus der Lösch-Liste
if server_name in deleted_servers: if server_name in deleted_servers:
deleted_servers.remove(server_name) deleted_servers.remove(server_name)
@ -30,7 +28,6 @@ def update():
@app.route('/delete', methods=['POST']) @app.route('/delete', methods=['POST'])
def delete_entry(): def delete_entry():
"""Markiert einen Server als gelöscht, damit er nicht mehr angezeigt wird"""
data = request.json data = request.json
server_name = data.get("server") server_name = data.get("server")
if not server_name or server_name not in proxy_data: if not server_name or server_name not in proxy_data:
@ -39,5 +36,14 @@ def delete_entry():
deleted_servers.add(server_name) deleted_servers.add(server_name)
return jsonify({"message": f"Server {server_name} deleted"}), 200 return jsonify({"message": f"Server {server_name} deleted"}), 200
@app.route('/status/<domain>')
def check_status(domain):
"""Check if a subdomain is reachable"""
try:
response = requests.get(f"https://{domain}", timeout=3)
return jsonify({"status": response.status_code})
except requests.exceptions.RequestException:
return jsonify({"status": "offline"})
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000) app.run(host='0.0.0.0', port=5000)

View file

@ -1 +1,2 @@
flask flask
requests

View file

@ -2,16 +2,19 @@
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Zentrales Caddy-Dashboard</title> <title>Caddy Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script> <script>
function toggleServer(id) { function toggleSearch() {
let section = document.getElementById("server-" + id); let searchBar = document.getElementById("search-box");
section.classList.toggle("hidden"); searchBar.classList.toggle("hidden");
if (!searchBar.classList.contains("hidden")) {
searchBar.focus();
}
} }
function filterEntries() { function filterEntries() {
let query = document.getElementById("search").value.toLowerCase(); let query = document.getElementById("search-box").value.toLowerCase();
let rows = document.querySelectorAll("tbody tr"); let rows = document.querySelectorAll("tbody tr");
rows.forEach(row => { rows.forEach(row => {
let domain = row.dataset.domain.toLowerCase(); let domain = row.dataset.domain.toLowerCase();
@ -30,44 +33,71 @@
} }
}); });
} }
function checkStatus(domain, element) {
fetch(`/status/${domain}`)
.then(response => response.json())
.then(data => {
if (data.status === "offline") {
element.innerHTML = "🔴 Offline";
element.classList.add("text-red-500");
} else {
element.innerHTML = "🟢 Online";
element.classList.add("text-green-500");
}
});
}
document.addEventListener("keydown", function(event) {
if (event.key === "/") {
event.preventDefault();
toggleSearch();
}
});
</script> </script>
</head> </head>
<body class="bg-gray-900 text-gray-100"> <body class="bg-gray-900 text-gray-100">
<header class="bg-indigo-700 text-white p-4 text-center">
<h1 class="text-2xl font-bold">Zentrales Caddy-Dashboard</h1> <header class="bg-indigo-700 text-white p-6 text-center">
<h1 class="text-3xl font-bold">Caddy Dashboard</h1>
<p class="text-cyan-300">Übersicht über alle aktiven Proxy-Server</p>
<button onclick="toggleSearch()" class="bg-cyan-500 hover:bg-cyan-400 text-white px-4 py-2 rounded mt-3">🔍 Suche</button>
</header> </header>
<div class="container mx-auto p-6"> <div class="container mx-auto p-6">
<input type="text" id="search" class="w-full p-2 mb-4 text-gray-900 rounded-md" placeholder="🔍 Suche nach einer Subdomain..." onkeyup="filterEntries()"> <input type="text" id="search-box" class="hidden w-full p-2 mb-4 text-gray-900 rounded-md" placeholder="🔍 Suche nach einer Subdomain..." onkeyup="filterEntries()">
{% for server, entries in proxies.items() %} {% for server, entries in proxies.items() %}
<div id="server-box-{{ server }}" class="bg-gray-800 p-4 rounded-md mb-6"> <div id="server-box-{{ server }}" class="bg-gray-800 p-4 rounded-md shadow-md mb-6">
<div class="flex justify-between"> <div class="flex justify-between items-center">
<button onclick="toggleServer('{{ server }}')" class="text-lg font-semibold text-indigo-400"> <h2 class="text-xl font-semibold text-indigo-400">{{ server }}</h2>
{{ server }}
</button>
<button onclick="deleteServer('{{ server }}')" class="bg-red-500 text-white px-3 py-1 rounded-md">🗑️ Löschen</button> <button onclick="deleteServer('{{ server }}')" class="bg-red-500 text-white px-3 py-1 rounded-md">🗑️ Löschen</button>
</div> </div>
<div id="server-{{ server }}" class="mt-2 hidden"> <table class="w-full mt-3 border-collapse border border-gray-700">
<table class="w-full mt-3"> <thead>
<thead> <tr class="text-cyan-400 bg-gray-700">
<tr class="text-cyan-400"> <th class="text-left p-3">Domain</th>
<th class="text-left p-2">Domain</th> <th class="text-left p-3">Ziel</th>
<th class="text-left p-2">Ziel</th> <th class="text-left p-3">Status</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for domain, target in entries.items() %} {% for domain, target in entries.items() %}
<tr data-domain="{{ domain }}"> <tr data-domain="{{ domain }}">
<td class="p-2"><a href="https://{{ domain }}" target="_blank" class="text-indigo-400">{{ domain }}</a></td> <td class="p-3 border border-gray-700">
<td class="p-2">{{ target }}</td> <a href="https://{{ domain }}" target="_blank" class="text-indigo-400 hover:text-indigo-300">{{ domain }}</a>
</tr> </td>
{% endfor %} <td class="p-3 border border-gray-700">{{ target }}</td>
</tbody> <td class="p-3 border border-gray-700">
</table> <button onclick="checkStatus('{{ domain }}', this)" class="bg-cyan-500 text-white px-3 py-1 rounded-md">🔄 Prüfen</button>
</div> </td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
</body> </body>
</html> </html>