Update app.py
Browse files
app.py
CHANGED
|
@@ -3,29 +3,29 @@ from flask import Flask, render_template_string, request, Response, jsonify
|
|
| 3 |
|
| 4 |
app = Flask(__name__)
|
| 5 |
log_queue = []
|
| 6 |
-
#
|
| 7 |
BOT_ROOT = os.path.join(os.getcwd(), "bot_workdir")
|
| 8 |
|
| 9 |
-
# UI Dashboard
|
| 10 |
HTML_TEMPLATE = """
|
| 11 |
<!DOCTYPE html>
|
| 12 |
<html>
|
| 13 |
<head>
|
| 14 |
-
<title>AQSO DEPLOYER
|
| 15 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 16 |
<style>
|
| 17 |
body { background: #0b0f1a; color: #cbd5e1; font-family: 'Fira Code', monospace; }
|
| 18 |
-
.terminal { background: #000; color: #10b981; padding: 12px; border-radius: 8px; height: 350px; overflow-y: auto; font-size: 11px; border: 1px solid #1e293b; }
|
|
|
|
| 19 |
.btn-gacor { transition: all 0.2s; font-weight: bold; border-radius: 8px; }
|
| 20 |
.btn-gacor:active { transform: scale(0.95); }
|
| 21 |
-
.status-bar { font-size: 10px; background: #1e293b; padding: 5px 10px; border-radius: 5px; color: #94a3b8; }
|
| 22 |
</style>
|
| 23 |
</head>
|
| 24 |
<body class="p-4 md:p-10">
|
| 25 |
<div class="max-w-4xl mx-auto">
|
| 26 |
<div class="flex justify-between items-center mb-6">
|
| 27 |
-
<h1 class="text-2xl font-bold text-blue-500">AQSO CLOUD
|
| 28 |
-
<div class="
|
| 29 |
</div>
|
| 30 |
|
| 31 |
<div class="bg-slate-900 p-6 rounded-2xl border border-slate-800 shadow-2xl space-y-4">
|
|
@@ -35,21 +35,18 @@ HTML_TEMPLATE = """
|
|
| 35 |
</div>
|
| 36 |
|
| 37 |
<div class="flex gap-2">
|
| 38 |
-
<input id="repo" type="text" class="flex-1 p-3 bg-black rounded-lg border border-slate-700 text-xs outline-none focus:border-blue-500" placeholder="Paste URL Github
|
| 39 |
<button onclick="runCmd('clone')" class="bg-blue-600 px-6 rounded-lg text-xs btn-gacor">CLONE</button>
|
| 40 |
</div>
|
| 41 |
|
| 42 |
-
<div class="terminal" id="logs">Sistem Siap.
|
|
|
|
| 43 |
|
| 44 |
-
<div class="grid grid-cols-3 gap-3">
|
| 45 |
<button onclick="runCmd('install')" class="bg-purple-700 py-3 text-xs btn-gacor">INSTALL DEPS</button>
|
| 46 |
<button onclick="runCmd('start')" class="bg-red-600 py-3 text-xs btn-gacor text-white">START BOT</button>
|
| 47 |
<button onclick="runCmd('clear')" class="bg-slate-700 py-3 text-xs btn-gacor">WIPE & RESET</button>
|
| 48 |
</div>
|
| 49 |
-
|
| 50 |
-
<p class="text-[10px] text-center text-slate-500 italic">
|
| 51 |
-
*Nggak perlu cd lagi. Sistem otomatis masuk ke folder bot lu.
|
| 52 |
-
</p>
|
| 53 |
</div>
|
| 54 |
</div>
|
| 55 |
|
|
@@ -61,12 +58,20 @@ HTML_TEMPLATE = """
|
|
| 61 |
document.getElementById('tag-py').className = l === 'python' ? 'flex-1 py-2 rounded bg-yellow-900 text-yellow-300 border border-yellow-500' : 'flex-1 py-2 rounded bg-slate-800 text-slate-500';
|
| 62 |
}
|
| 63 |
|
| 64 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
const repo = document.getElementById('repo').value;
|
| 66 |
fetch('/execute', {
|
| 67 |
method: 'POST',
|
| 68 |
headers: {'Content-Type': 'application/json'},
|
| 69 |
-
body: JSON.stringify({type, repo, lang})
|
| 70 |
});
|
| 71 |
}
|
| 72 |
|
|
@@ -84,7 +89,9 @@ HTML_TEMPLATE = """
|
|
| 84 |
def run_command(command, cwd=None):
|
| 85 |
global log_queue
|
| 86 |
if not os.path.exists(cwd): os.makedirs(cwd)
|
| 87 |
-
|
|
|
|
|
|
|
| 88 |
for line in process.stdout:
|
| 89 |
log_queue.append(f"> {line.strip()}")
|
| 90 |
process.wait()
|
|
@@ -95,29 +102,30 @@ def index(): return render_template_string(HTML_TEMPLATE)
|
|
| 95 |
@app.route('/execute', methods=['POST'])
|
| 96 |
def execute():
|
| 97 |
data = request.json
|
| 98 |
-
cmd_type, repo, lang = data['type'], data['repo'], data['lang']
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
-
|
| 101 |
if os.path.exists(BOT_ROOT): shutil.rmtree(BOT_ROOT)
|
| 102 |
-
log_queue.append("<span class='text-orange-400'>[SYSTEM] Workspace
|
| 103 |
|
| 104 |
elif cmd_type == 'clone':
|
| 105 |
-
# Bersihkan dulu folder bot_workdir biar nggak bentrok
|
| 106 |
if os.path.exists(BOT_ROOT): shutil.rmtree(BOT_ROOT)
|
| 107 |
os.makedirs(BOT_ROOT)
|
| 108 |
-
# Clone langsung isi repo ke bot_workdir
|
| 109 |
log_queue.append(f"[SYSTEM] Cloning ke folder khusus...")
|
| 110 |
threading.Thread(target=run_command, args=(f"git clone {repo} .", BOT_ROOT)).start()
|
| 111 |
|
| 112 |
elif cmd_type == 'install':
|
| 113 |
cmd = "npm install" if lang == 'node' else "pip install -r requirements.txt"
|
| 114 |
-
log_queue.append(f"[SYSTEM] Menjalankan {cmd} di folder khusus...")
|
| 115 |
threading.Thread(target=run_command, args=(cmd, BOT_ROOT)).start()
|
| 116 |
|
| 117 |
elif cmd_type == 'start':
|
| 118 |
-
#
|
| 119 |
cmd = "exec -a 'python3_inference' node ." if lang == 'node' else "exec -a 'python3_inference' python3 main.py"
|
| 120 |
-
log_queue.append(f"[SYSTEM] Menjalankan bot
|
| 121 |
threading.Thread(target=run_command, args=(cmd, BOT_ROOT)).start()
|
| 122 |
|
| 123 |
return {"status": "ok"}
|
|
@@ -132,3 +140,4 @@ def stream():
|
|
| 132 |
|
| 133 |
if __name__ == "__main__":
|
| 134 |
app.run(host='0.0.0.0', port=7860)
|
|
|
|
|
|
| 3 |
|
| 4 |
app = Flask(__name__)
|
| 5 |
log_queue = []
|
| 6 |
+
# PATH TETAP: Semua bot ditaruh di sini
|
| 7 |
BOT_ROOT = os.path.join(os.getcwd(), "bot_workdir")
|
| 8 |
|
| 9 |
+
# UI Dashboard v6 - Ultimate Terminal Edition
|
| 10 |
HTML_TEMPLATE = """
|
| 11 |
<!DOCTYPE html>
|
| 12 |
<html>
|
| 13 |
<head>
|
| 14 |
+
<title>AQSO DEPLOYER v6</title>
|
| 15 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 16 |
<style>
|
| 17 |
body { background: #0b0f1a; color: #cbd5e1; font-family: 'Fira Code', monospace; }
|
| 18 |
+
.terminal { background: #000; color: #10b981; padding: 12px; border-radius: 8px 8px 0 0; height: 350px; overflow-y: auto; font-size: 11px; border: 1px solid #1e293b; }
|
| 19 |
+
.term-input { background: #000; color: #fff; border: 1px solid #1e293b; border-top: none; width: 100%; padding: 10px; font-size: 11px; border-radius: 0 0 8px 8px; outline: none; }
|
| 20 |
.btn-gacor { transition: all 0.2s; font-weight: bold; border-radius: 8px; }
|
| 21 |
.btn-gacor:active { transform: scale(0.95); }
|
|
|
|
| 22 |
</style>
|
| 23 |
</head>
|
| 24 |
<body class="p-4 md:p-10">
|
| 25 |
<div class="max-w-4xl mx-auto">
|
| 26 |
<div class="flex justify-between items-center mb-6">
|
| 27 |
+
<h1 class="text-2xl font-bold text-blue-500">AQSO CLOUD v6 ⚡</h1>
|
| 28 |
+
<div class="text-[10px] bg-slate-800 px-3 py-1 rounded text-slate-400">PATH: /bot_workdir</div>
|
| 29 |
</div>
|
| 30 |
|
| 31 |
<div class="bg-slate-900 p-6 rounded-2xl border border-slate-800 shadow-2xl space-y-4">
|
|
|
|
| 35 |
</div>
|
| 36 |
|
| 37 |
<div class="flex gap-2">
|
| 38 |
+
<input id="repo" type="text" class="flex-1 p-3 bg-black rounded-lg border border-slate-700 text-xs outline-none focus:border-blue-500" placeholder="Paste URL Github Lu...">
|
| 39 |
<button onclick="runCmd('clone')" class="bg-blue-600 px-6 rounded-lg text-xs btn-gacor">CLONE</button>
|
| 40 |
</div>
|
| 41 |
|
| 42 |
+
<div class="terminal" id="logs">Sistem Siap. Terminal manual di bawah otomatis jalan di folder bot lu.</div>
|
| 43 |
+
<input type="text" id="term-box" class="term-input" placeholder="Ketik command manual (contoh: ls -la atau npm install) lalu Enter..." onkeypress="handleTerm(event)">
|
| 44 |
|
| 45 |
+
<div class="grid grid-cols-3 gap-3 mt-4">
|
| 46 |
<button onclick="runCmd('install')" class="bg-purple-700 py-3 text-xs btn-gacor">INSTALL DEPS</button>
|
| 47 |
<button onclick="runCmd('start')" class="bg-red-600 py-3 text-xs btn-gacor text-white">START BOT</button>
|
| 48 |
<button onclick="runCmd('clear')" class="bg-slate-700 py-3 text-xs btn-gacor">WIPE & RESET</button>
|
| 49 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
</div>
|
| 51 |
</div>
|
| 52 |
|
|
|
|
| 58 |
document.getElementById('tag-py').className = l === 'python' ? 'flex-1 py-2 rounded bg-yellow-900 text-yellow-300 border border-yellow-500' : 'flex-1 py-2 rounded bg-slate-800 text-slate-500';
|
| 59 |
}
|
| 60 |
|
| 61 |
+
function handleTerm(e) {
|
| 62 |
+
if (e.key === 'Enter') {
|
| 63 |
+
const cmd = e.target.value;
|
| 64 |
+
runCmd('manual', cmd);
|
| 65 |
+
e.target.value = '';
|
| 66 |
+
}
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
function runCmd(type, manualCmd = '') {
|
| 70 |
const repo = document.getElementById('repo').value;
|
| 71 |
fetch('/execute', {
|
| 72 |
method: 'POST',
|
| 73 |
headers: {'Content-Type': 'application/json'},
|
| 74 |
+
body: JSON.stringify({type, repo, lang, manual: manualCmd})
|
| 75 |
});
|
| 76 |
}
|
| 77 |
|
|
|
|
| 89 |
def run_command(command, cwd=None):
|
| 90 |
global log_queue
|
| 91 |
if not os.path.exists(cwd): os.makedirs(cwd)
|
| 92 |
+
# Gunakan bash -c agar 'exec -a' bisa jalan
|
| 93 |
+
full_cmd = f"bash -c \"{command}\""
|
| 94 |
+
process = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=cwd)
|
| 95 |
for line in process.stdout:
|
| 96 |
log_queue.append(f"> {line.strip()}")
|
| 97 |
process.wait()
|
|
|
|
| 102 |
@app.route('/execute', methods=['POST'])
|
| 103 |
def execute():
|
| 104 |
data = request.json
|
| 105 |
+
cmd_type, repo, lang, manual = data['type'], data['repo'], data['lang'], data.get('manual', '')
|
| 106 |
+
|
| 107 |
+
if cmd_type == 'manual':
|
| 108 |
+
log_queue.append(f"<span class='text-blue-400'>[MANUAL] {manual}</span>")
|
| 109 |
+
threading.Thread(target=run_command, args=(manual, BOT_ROOT)).start()
|
| 110 |
|
| 111 |
+
elif cmd_type == 'clear':
|
| 112 |
if os.path.exists(BOT_ROOT): shutil.rmtree(BOT_ROOT)
|
| 113 |
+
log_queue.append("<span class='text-orange-400'>[SYSTEM] Workspace Cleaned.</span>")
|
| 114 |
|
| 115 |
elif cmd_type == 'clone':
|
|
|
|
| 116 |
if os.path.exists(BOT_ROOT): shutil.rmtree(BOT_ROOT)
|
| 117 |
os.makedirs(BOT_ROOT)
|
|
|
|
| 118 |
log_queue.append(f"[SYSTEM] Cloning ke folder khusus...")
|
| 119 |
threading.Thread(target=run_command, args=(f"git clone {repo} .", BOT_ROOT)).start()
|
| 120 |
|
| 121 |
elif cmd_type == 'install':
|
| 122 |
cmd = "npm install" if lang == 'node' else "pip install -r requirements.txt"
|
|
|
|
| 123 |
threading.Thread(target=run_command, args=(cmd, BOT_ROOT)).start()
|
| 124 |
|
| 125 |
elif cmd_type == 'start':
|
| 126 |
+
# FIX: Pakai bash -c biar 'exec -a' gak error lagi
|
| 127 |
cmd = "exec -a 'python3_inference' node ." if lang == 'node' else "exec -a 'python3_inference' python3 main.py"
|
| 128 |
+
log_queue.append(f"<span class='text-red-400'>[SYSTEM] Menjalankan bot (Masking Bash)...</span>")
|
| 129 |
threading.Thread(target=run_command, args=(cmd, BOT_ROOT)).start()
|
| 130 |
|
| 131 |
return {"status": "ok"}
|
|
|
|
| 140 |
|
| 141 |
if __name__ == "__main__":
|
| 142 |
app.run(host='0.0.0.0', port=7860)
|
| 143 |
+
|