batman dev

This commit is contained in:
pika 2025-03-22 10:35:17 +01:00
parent a4ce8a291d
commit de000c7ac6
10 changed files with 389 additions and 34 deletions

88
app.py
View file

@ -1,33 +1,83 @@
from flask import Flask, render_template, request, jsonify
from flask import Flask, render_template, request, jsonify, abort
import requests
import threading
import secrets
import os
import hashlib
import time
from functools import wraps
app = Flask(__name__)
# Generate a secure API key if not already set in environment
if not os.environ.get('CADDYDB_API_KEY'):
app.config['API_KEY'] = os.environ.get('CADDYDB_API_KEY', secrets.token_hex(32))
print(f"API Key: {app.config['API_KEY']} - Store this securely!")
else:
app.config['API_KEY'] = os.environ.get('CADDYDB_API_KEY')
proxy_data = {}
deleted_servers = set()
# Authentication decorator
def require_api_key(f):
@wraps(f)
def decorated_function(*args, **kwargs):
api_key = request.headers.get('X-API-Key')
if not api_key or api_key != app.config['API_KEY']:
return jsonify({"error": "Unauthorized access"}), 401
return f(*args, **kwargs)
return decorated_function
@app.route('/')
def index():
filtered_data = {k: v for k, v in proxy_data.items() if k not in deleted_servers}
return render_template('index.html', proxies=filtered_data)
@app.route('/update', methods=['POST'])
def update():
@app.route('/api/update', methods=['POST'])
@require_api_key
def api_update():
data = request.json
if not data or "server" not in data or "entries" not in data:
return jsonify({"error": "Invalid data"}), 400
server_name = data["server"]
proxy_data[server_name] = data["entries"]
source_type = data.get("source_type", "caddy") # Default to caddy if not specified
proxy_data[server_name] = {
"entries": data["entries"],
"source_type": source_type,
"last_updated": time.time()
}
if server_name in deleted_servers:
deleted_servers.remove(server_name)
return jsonify({"message": "Updated successfully"}), 200
@app.route('/delete', methods=['POST'])
def delete_entry():
# Legacy endpoint for backward compatibility
@app.route('/update', methods=['POST'])
@require_api_key
def update():
data = request.json
if not data or "server" not in data or "entries" not in data:
return jsonify({"error": "Invalid data"}), 400
server_name = data["server"]
proxy_data[server_name] = {
"entries": data["entries"],
"source_type": "caddy",
"last_updated": time.time()
}
if server_name in deleted_servers:
deleted_servers.remove(server_name)
return jsonify({"message": "Updated successfully"}), 200
@app.route('/api/delete', methods=['POST'])
@require_api_key
def api_delete_entry():
data = request.json
server_name = data.get("server")
if not server_name or server_name not in proxy_data:
@ -36,8 +86,14 @@ def delete_entry():
deleted_servers.add(server_name)
return jsonify({"message": f"Server {server_name} deleted"}), 200
@app.route('/status/<domain>')
def check_status(domain):
# Legacy endpoint for backward compatibility
@app.route('/delete', methods=['POST'])
@require_api_key
def delete_entry():
return api_delete_entry()
@app.route('/api/status/<domain>')
def api_check_status(domain):
"""Check if a subdomain is reachable"""
try:
response = requests.get(f"https://{domain}", timeout=3)
@ -45,5 +101,17 @@ def check_status(domain):
except requests.exceptions.RequestException:
return jsonify({"status": "offline"})
# Legacy endpoint for backward compatibility
@app.route('/status/<domain>')
def check_status(domain):
return api_check_status(domain)
@app.route('/api/servers', methods=['GET'])
@require_api_key
def list_servers():
"""List all registered servers"""
filtered_data = {k: v for k, v in proxy_data.items() if k not in deleted_servers}
return jsonify({"servers": list(filtered_data.keys())}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
app.run(host='0.0.0.0', port=5000, ssl_context='adhoc') # Using adhoc SSL for development