# panel.py — Tek Dosya VDS Panel # Kurulum: pip install flask flask-cors # Çalıştır: python3 panel.py # Erişim: http://VDS_IP:8080 import os, re, base64, subprocess, uuid, sys, ast from flask import Flask, request, jsonify, Response from flask_cors import CORS app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) UPLOAD_DIR = "uploads" os.makedirs(UPLOAD_DIR, exist_ok=True) RUNNING = {} # pid -> {file, log, proc} ANDROID_ONLY = { "android","pyjnius","jnius","kivy","plyer", "pydroid","sl4a","androidhelper","chaquopy", "beeware","briefcase","toga" } # ---------- HTML (gömülü) ---------- INDEX_HTML = r""" VDS Panel

VDS PANEL

Pydroid .py Runner — Telegram Bot Auto-Run
Backend bekleniyor...

+ Pydroid .py dosyası yükle

sürükle-bırak veya tıkla

""" # ---------- Yardımcılar ---------- def find_imports(code: str): mods = set() try: tree = ast.parse(code) except SyntaxError: for line in code.splitlines(): m = re.match(r"^\s*(?:import|from)\s+([\w\.]+)", line) if m: mods.add(m.group(1).split(".")[0]) return mods for node in ast.walk(tree): if isinstance(node, ast.Import): for n in node.names: mods.add(n.name.split(".")[0]) elif isinstance(node, ast.ImportFrom): if node.module: mods.add(node.module.split(".")[0]) return mods # ---------- Rotalar ---------- @app.route("/") def index(): return Response(INDEX_HTML, mimetype="text/html") @app.route("/ping") def ping(): return jsonify(status="ok") @app.route("/upload", methods=["POST","OPTIONS"]) def upload(): if request.method == "OPTIONS": return ("", 204) try: data = request.get_json() filename = data.get("filename", "script.py") content_b64 = data.get("content", "") raw = base64.b64decode(content_b64) code = raw.decode("utf-8", errors="replace") blocked = find_imports(code) & ANDROID_ONLY if blocked: return jsonify(error=f"Android-only: {', '.join(sorted(blocked))}"), 400 safe = f"{uuid.uuid4().hex[:8]}_{os.path.basename(filename)}" path = os.path.join(UPLOAD_DIR, safe) with open(path, "wb") as f: f.write(raw) log_path = path + ".log" log_f = open(log_path, "ab") proc = subprocess.Popen( [sys.executable, "-u", path], stdout=log_f, stderr=log_f, stdin=subprocess.DEVNULL, start_new_session=True, cwd=UPLOAD_DIR ) RUNNING[proc.pid] = {"file": path, "log": log_path, "proc": proc} return jsonify(ok=True, pid=proc.pid, file=safe) except Exception as e: return jsonify(error=str(e)), 500 @app.route("/processes") def processes(): return jsonify({pid: i["file"] for pid, i in RUNNING.items() if i["proc"].poll() is None}) @app.route("/logs/") def logs(pid): i = RUNNING.get(pid) if not i: return jsonify(error="pid yok"), 404 with open(i["log"], "r", errors="replace") as f: return jsonify(log="".join(f.readlines()[-200:])) if __name__ == "__main__": print("VDS Panel → http://0.0.0.0:8080") app.run(host="0.0.0.0", port=8080, debug=False)