THEZYZSTUDIO commited on
Commit
1a9aae2
ยท
verified ยท
1 Parent(s): bbefc13

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +48 -0
  2. app.py +413 -0
  3. requirements.txt +9 -0
Dockerfile ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
2
+ # LINUX SYSTEM SERVER โ€” Dockerfile
3
+ # ุฎุงุต ุจู€: ุณูŠุฑูุฑ 2 (ุณูŠุฑูุฑ ู†ุธุงู… Linux)
4
+ # Belongs to: SERVER 2 (Linux System Server)
5
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
6
+
7
+ FROM python:3.10-slim
8
+
9
+ WORKDIR /app
10
+
11
+ # ุชุซุจูŠุช ุฃุฏูˆุงุช ุงู„ู†ุธุงู… ุงู„ุฃุณุงุณูŠุฉ (Linux tools)
12
+ RUN apt-get update && apt-get install -y --no-install-recommends \
13
+ curl \
14
+ wget \
15
+ git \
16
+ vim \
17
+ nano \
18
+ htop \
19
+ tree \
20
+ unzip \
21
+ zip \
22
+ net-tools \
23
+ iputils-ping \
24
+ procps \
25
+ build-essential \
26
+ python3-dev \
27
+ nodejs \
28
+ npm \
29
+ && rm -rf /var/lib/apt/lists/*
30
+
31
+ # ุฅู†ุดุงุก ู…ุฌู„ุฏ workspace
32
+ RUN mkdir -p /workspace
33
+
34
+ # ุชุซุจูŠุช ู…ูƒุชุจุงุช Python
35
+ COPY requirements.txt .
36
+ RUN pip install --no-cache-dir --upgrade pip && \
37
+ pip install --no-cache-dir -r requirements.txt
38
+
39
+ # ู†ุณุฎ ู…ู„ูุงุช ุงู„ู…ุดุฑูˆุน
40
+ COPY . .
41
+
42
+ # ุงู„ู…ู†ูุฐ ุงู„ุฎุงุต ุจู€ Hugging Face
43
+ EXPOSE 7860
44
+
45
+ # ู…ุชุบูŠุฑ ุงู„ุจูŠุฆุฉ ุงู„ุงูุชุฑุงุถูŠ (ูŠู…ูƒู† ุชุบูŠูŠุฑู‡ ููŠ ุฅุนุฏุงุฏุงุช HF Space)
46
+ ENV LINUX_API_TOKEN="zyz-linux-secret-2025"
47
+
48
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
3
+ โ•‘ LINUX SYSTEM SERVER โ€” by BU THE ZYZ STUDIO โ•‘
4
+ โ•‘ ๐Ÿ–ฅ๏ธ ุณูŠุฑูุฑ ู†ุธุงู… ู„ูŠู†ูƒุณ โ€” ูŠูุชุญูƒู… ููŠู‡ ุนุจุฑ ุงู„ุณูŠุฑูุฑ ุงู„ุฃูˆู„ โ•‘
5
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
6
+
7
+ ู‡ุฐุง ุงู„ู…ู„ู ุฎุงุต ุจู€: ุณูŠุฑูุฑ 2 (ุณูŠุฑูุฑ ู†ุธุงู… Linux)
8
+ This file belongs to: SERVER 2 (Linux System Server)
9
+ """
10
+
11
+ import os
12
+ import subprocess
13
+ import json
14
+ import threading
15
+ import time
16
+ import shutil
17
+ import signal
18
+ from pathlib import Path
19
+ from flask import Flask, request, jsonify, Response, stream_with_context
20
+ from flask_cors import CORS
21
+
22
+ app = Flask(__name__)
23
+ CORS(app, resources={r"/api/*": {"origins": "*"}})
24
+
25
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
26
+ # ๐Ÿ” Security Token โ€” ุฑู…ุฒ ุงู„ุฃู…ุงู†
27
+ # Set as environment variable: LINUX_API_TOKEN
28
+ # ุนูŠู‘ู† ู‡ุฐุง ุงู„ู…ุชุบูŠุฑ ููŠ ุฅุนุฏุงุฏุงุช Hugging Face Space
29
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
30
+ API_TOKEN = os.environ.get("LINUX_API_TOKEN", "zyz-linux-secret-2025")
31
+
32
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
33
+ # ๐Ÿ“ Workspace Directory
34
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
35
+ WORKSPACE = "/workspace"
36
+ os.makedirs(WORKSPACE, exist_ok=True)
37
+
38
+ # Active processes store (for killing long-running processes)
39
+ active_processes = {}
40
+ process_lock = threading.Lock()
41
+
42
+
43
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
44
+ # ๐Ÿ”’ Auth Helper
45
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
46
+ def verify_token(req) -> bool:
47
+ """ุงู„ุชุญู‚ู‚ ู…ู† ุฑู…ุฒ ุงู„ุฃู…ุงู† ููŠ ุงู„ุทู„ุจ"""
48
+ # Check header first
49
+ token_header = req.headers.get("X-API-Token", "")
50
+ if token_header == API_TOKEN:
51
+ return True
52
+ # Check JSON body
53
+ if req.is_json:
54
+ body = req.get_json(silent=True) or {}
55
+ if body.get("token", "") == API_TOKEN:
56
+ return True
57
+ return False
58
+
59
+
60
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
61
+ # โœ… Status Endpoint
62
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
63
+ @app.route("/")
64
+ def root():
65
+ return jsonify({
66
+ "name": "Linux System Server",
67
+ "version": "1.0.0",
68
+ "by": "BU THE ZYZ STUDIO",
69
+ "status": "online",
70
+ "note": "Use /api/status with your token to verify authentication."
71
+ })
72
+
73
+
74
+ @app.route("/api/status")
75
+ def status():
76
+ """ุญุงู„ุฉ ุงู„ุณูŠุฑูุฑ โ€” ูŠุนู…ู„ ุจุฏูˆู† ุชูˆุซูŠู‚ ู„ู„ุชุญู‚ู‚ ู…ู† ุงู„ุงุชุตุงู„"""
77
+ try:
78
+ uname = subprocess.run("uname -a", shell=True, capture_output=True, text=True, timeout=5)
79
+ disk = subprocess.run("df -h /workspace 2>/dev/null || df -h /", shell=True, capture_output=True, text=True, timeout=5)
80
+ mem = subprocess.run("free -h", shell=True, capture_output=True, text=True, timeout=5)
81
+ python = subprocess.run("python3 --version", shell=True, capture_output=True, text=True, timeout=5)
82
+ except Exception:
83
+ uname = disk = mem = python = type("R", (), {"stdout": "N/A", "stderr": ""})()
84
+
85
+ authenticated = verify_token(request)
86
+ return jsonify({
87
+ "status": "online",
88
+ "authenticated": authenticated,
89
+ "system": uname.stdout.strip(),
90
+ "disk": disk.stdout.strip(),
91
+ "memory": mem.stdout.strip(),
92
+ "python": python.stdout.strip(),
93
+ "workspace": WORKSPACE,
94
+ "timestamp": time.time()
95
+ })
96
+
97
+
98
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
99
+ # โšก Execute Command โ€” ุชู†ููŠุฐ ุฃูˆุงู…ุฑ ุงู„ุชุฑู…ูŠู†ุงู„
100
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
101
+ @app.route("/api/execute", methods=["POST"])
102
+ def execute_command():
103
+ """
104
+ ุชู†ููŠุฐ ุฃู…ุฑ ุชุฑู…ูŠู†ุงู„ ูˆุงุญุฏ ูˆุงู„ุญุตูˆู„ ุนู„ู‰ ุงู„ู†ุชูŠุฌุฉ ูƒุงู…ู„ุฉ
105
+ Execute a single terminal command and get full output
106
+ """
107
+ if not verify_token(request):
108
+ return jsonify({"error": "Unauthorized โ€” Invalid or missing API token"}), 401
109
+
110
+ data = request.get_json(silent=True) or {}
111
+ command = data.get("command", "").strip()
112
+ cwd = data.get("cwd", WORKSPACE)
113
+ timeout = min(int(data.get("timeout", 30)), 300) # max 5 minutes
114
+
115
+ if not command:
116
+ return jsonify({"error": "No command provided"}), 400
117
+
118
+ # Validate working directory
119
+ if not os.path.exists(cwd):
120
+ cwd = WORKSPACE
121
+
122
+ try:
123
+ result = subprocess.run(
124
+ command,
125
+ shell=True,
126
+ capture_output=True,
127
+ text=True,
128
+ cwd=cwd,
129
+ timeout=timeout,
130
+ env={**os.environ, "HOME": "/root", "TERM": "xterm-256color"}
131
+ )
132
+ return jsonify({
133
+ "success": True,
134
+ "stdout": result.stdout,
135
+ "stderr": result.stderr,
136
+ "returncode": result.returncode,
137
+ "command": command,
138
+ "cwd": cwd
139
+ })
140
+ except subprocess.TimeoutExpired:
141
+ return jsonify({
142
+ "success": False,
143
+ "error": f"Command timed out after {timeout} seconds",
144
+ "returncode": -1
145
+ }), 408
146
+ except Exception as e:
147
+ return jsonify({
148
+ "success": False,
149
+ "error": str(e),
150
+ "returncode": -1
151
+ }), 500
152
+
153
+
154
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
155
+ # ๐Ÿ“ก Stream Execute โ€” ุชู†ููŠุฐ ู…ุน ุจุซ ุงู„ู†ุชุงุฆุฌ
156
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
157
+ @app.route("/api/stream", methods=["POST"])
158
+ def stream_execute():
159
+ """
160
+ ุชู†ููŠุฐ ุฃู…ุฑ ู…ุน ุจุซ ุงู„ู…ุฎุฑุฌุงุช ุณุทุฑุงู‹ ุจุณุทุฑ (ู…ููŠุฏ ู„ู„ุฃูˆุงู…ุฑ ุงู„ุทูˆูŠู„ุฉ)
161
+ Stream command output line by line (useful for long-running commands)
162
+ """
163
+ if not verify_token(request):
164
+ return jsonify({"error": "Unauthorized"}), 401
165
+
166
+ data = request.get_json(silent=True) or {}
167
+ command = data.get("command", "").strip()
168
+ cwd = data.get("cwd", WORKSPACE)
169
+ pid_key = data.get("pid_key", f"proc_{int(time.time())}")
170
+
171
+ if not command:
172
+ return jsonify({"error": "No command provided"}), 400
173
+
174
+ if not os.path.exists(cwd):
175
+ cwd = WORKSPACE
176
+
177
+ @stream_with_context
178
+ def generate():
179
+ try:
180
+ process = subprocess.Popen(
181
+ command,
182
+ shell=True,
183
+ stdout=subprocess.PIPE,
184
+ stderr=subprocess.STDOUT,
185
+ text=True,
186
+ cwd=cwd,
187
+ env={**os.environ, "HOME": "/root", "TERM": "xterm-256color"},
188
+ bufsize=1
189
+ )
190
+ with process_lock:
191
+ active_processes[pid_key] = process
192
+
193
+ yield f"data: {json.dumps({'type': 'start', 'pid': process.pid, 'command': command})}\n\n"
194
+
195
+ for line in iter(process.stdout.readline, ""):
196
+ yield f"data: {json.dumps({'type': 'output', 'line': line})}\n\n"
197
+
198
+ process.wait()
199
+ with process_lock:
200
+ active_processes.pop(pid_key, None)
201
+
202
+ yield f"data: {json.dumps({'type': 'done', 'returncode': process.returncode})}\n\n"
203
+ yield "data: [DONE]\n\n"
204
+
205
+ except Exception as e:
206
+ yield f"data: {json.dumps({'type': 'error', 'message': str(e)})}\n\n"
207
+
208
+ return Response(
209
+ generate(),
210
+ mimetype="text/event-stream",
211
+ headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}
212
+ )
213
+
214
+
215
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
216
+ # ๐Ÿ›‘ Kill Process โ€” ุฅูŠู‚ุงู ุนู…ู„ูŠุฉ ุฌุงุฑูŠุฉ
217
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
218
+ @app.route("/api/kill", methods=["POST"])
219
+ def kill_process():
220
+ if not verify_token(request):
221
+ return jsonify({"error": "Unauthorized"}), 401
222
+ data = request.get_json(silent=True) or {}
223
+ pid_key = data.get("pid_key", "")
224
+ with process_lock:
225
+ proc = active_processes.get(pid_key)
226
+ if proc:
227
+ try:
228
+ proc.terminate()
229
+ time.sleep(0.5)
230
+ if proc.poll() is None:
231
+ proc.kill()
232
+ return jsonify({"success": True, "message": "Process terminated"})
233
+ except Exception as e:
234
+ return jsonify({"error": str(e)}), 500
235
+ return jsonify({"error": "Process not found"}), 404
236
+
237
+
238
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
239
+ # ๐Ÿ“ File System Operations
240
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
241
+ @app.route("/api/files/list", methods=["GET", "POST"])
242
+ def list_files():
243
+ """ู‚ุงุฆู…ุฉ ุงู„ู…ู„ูุงุช ููŠ ู…ุณุงุฑ ู…ุนูŠู†"""
244
+ if not verify_token(request):
245
+ return jsonify({"error": "Unauthorized"}), 401
246
+
247
+ if request.method == "POST":
248
+ data = request.get_json(silent=True) or {}
249
+ path = data.get("path", WORKSPACE)
250
+ else:
251
+ path = request.args.get("path", WORKSPACE)
252
+
253
+ try:
254
+ items = []
255
+ for name in sorted(os.listdir(path)):
256
+ full = os.path.join(path, name)
257
+ try:
258
+ stat = os.stat(full)
259
+ items.append({
260
+ "name": name,
261
+ "path": full,
262
+ "is_dir": os.path.isdir(full),
263
+ "size": stat.st_size,
264
+ "modified": stat.st_mtime
265
+ })
266
+ except Exception:
267
+ pass
268
+ return jsonify({"success": True, "path": path, "items": items})
269
+ except Exception as e:
270
+ return jsonify({"error": str(e)}), 500
271
+
272
+
273
+ @app.route("/api/files/read", methods=["POST"])
274
+ def read_file():
275
+ """ู‚ุฑุงุกุฉ ู…ุญุชูˆู‰ ู…ู„ู"""
276
+ if not verify_token(request):
277
+ return jsonify({"error": "Unauthorized"}), 401
278
+ data = request.get_json(silent=True) or {}
279
+ path = data.get("path", "").strip()
280
+ if not path:
281
+ return jsonify({"error": "No path provided"}), 400
282
+ try:
283
+ with open(path, "r", encoding="utf-8", errors="replace") as f:
284
+ content = f.read()
285
+ return jsonify({"success": True, "path": path, "content": content, "size": len(content)})
286
+ except Exception as e:
287
+ return jsonify({"error": str(e)}), 500
288
+
289
+
290
+ @app.route("/api/files/write", methods=["POST"])
291
+ def write_file():
292
+ """ูƒุชุงุจุฉ ู…ุญุชูˆู‰ ุฅู„ู‰ ู…ู„ู"""
293
+ if not verify_token(request):
294
+ return jsonify({"error": "Unauthorized"}), 401
295
+ data = request.get_json(silent=True) or {}
296
+ path = data.get("path", "").strip()
297
+ content = data.get("content", "")
298
+ if not path:
299
+ return jsonify({"error": "No path provided"}), 400
300
+ try:
301
+ dir_ = os.path.dirname(path)
302
+ if dir_:
303
+ os.makedirs(dir_, exist_ok=True)
304
+ with open(path, "w", encoding="utf-8") as f:
305
+ f.write(content)
306
+ return jsonify({"success": True, "path": path, "bytes_written": len(content.encode())})
307
+ except Exception as e:
308
+ return jsonify({"error": str(e)}), 500
309
+
310
+
311
+ @app.route("/api/files/delete", methods=["POST"])
312
+ def delete_file():
313
+ """ุญุฐู ู…ู„ู ุฃูˆ ู…ุฌู„ุฏ"""
314
+ if not verify_token(request):
315
+ return jsonify({"error": "Unauthorized"}), 401
316
+ data = request.get_json(silent=True) or {}
317
+ path = data.get("path", "").strip()
318
+ if not path:
319
+ return jsonify({"error": "No path provided"}), 400
320
+ try:
321
+ if os.path.isdir(path):
322
+ shutil.rmtree(path)
323
+ else:
324
+ os.remove(path)
325
+ return jsonify({"success": True, "deleted": path})
326
+ except Exception as e:
327
+ return jsonify({"error": str(e)}), 500
328
+
329
+
330
+ @app.route("/api/files/mkdir", methods=["POST"])
331
+ def make_dir():
332
+ """ุฅู†ุดุงุก ู…ุฌู„ุฏ ุฌุฏูŠุฏ"""
333
+ if not verify_token(request):
334
+ return jsonify({"error": "Unauthorized"}), 401
335
+ data = request.get_json(silent=True) or {}
336
+ path = data.get("path", "").strip()
337
+ try:
338
+ os.makedirs(path, exist_ok=True)
339
+ return jsonify({"success": True, "created": path})
340
+ except Exception as e:
341
+ return jsonify({"error": str(e)}), 500
342
+
343
+
344
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
345
+ # ๐Ÿ“ฆ Package Manager โ€” ุฅุฏุงุฑุฉ ุงู„ุญุฒู…
346
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
347
+ @app.route("/api/packages/install", methods=["POST"])
348
+ def install_package():
349
+ """ุชุซุจูŠุช ุญุฒู…ุฉ Python ุฃูˆ apt"""
350
+ if not verify_token(request):
351
+ return jsonify({"error": "Unauthorized"}), 401
352
+ data = request.get_json(silent=True) or {}
353
+ package = data.get("package", "").strip()
354
+ manager = data.get("manager", "pip") # "pip" or "apt"
355
+ if not package:
356
+ return jsonify({"error": "No package name"}), 400
357
+ try:
358
+ if manager == "apt":
359
+ cmd = f"apt-get install -y {package}"
360
+ else:
361
+ cmd = f"pip install {package}"
362
+ result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=120)
363
+ return jsonify({
364
+ "success": result.returncode == 0,
365
+ "stdout": result.stdout,
366
+ "stderr": result.stderr
367
+ })
368
+ except subprocess.TimeoutExpired:
369
+ return jsonify({"error": "Installation timed out"}), 408
370
+ except Exception as e:
371
+ return jsonify({"error": str(e)}), 500
372
+
373
+
374
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
375
+ # ๐Ÿ”ง System Info โ€” ู…ุนู„ูˆู…ุงุช ุงู„ู†ุธุงู…
376
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
377
+ @app.route("/api/sysinfo", methods=["GET", "POST"])
378
+ def sysinfo():
379
+ """ู…ุนู„ูˆู…ุงุช ุชูุตูŠู„ูŠุฉ ุนู† ุงู„ู†ุธุงู…"""
380
+ if not verify_token(request):
381
+ return jsonify({"error": "Unauthorized"}), 401
382
+
383
+ commands = {
384
+ "os": "cat /etc/os-release 2>/dev/null | head -5",
385
+ "cpu": "lscpu 2>/dev/null | grep -E 'Architecture|CPU\\(s\\)|Model name' | head -5",
386
+ "memory": "free -h",
387
+ "disk": "df -h",
388
+ "network": "ip addr show 2>/dev/null | grep 'inet ' | head -5",
389
+ "python": "python3 --version && pip3 list 2>/dev/null | head -20",
390
+ "processes":"ps aux --sort=-%cpu 2>/dev/null | head -10",
391
+ "uptime": "uptime"
392
+ }
393
+ info = {}
394
+ for key, cmd in commands.items():
395
+ try:
396
+ r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10)
397
+ info[key] = r.stdout.strip()
398
+ except Exception:
399
+ info[key] = "N/A"
400
+
401
+ return jsonify({"success": True, "info": info})
402
+
403
+
404
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
405
+ # ๐Ÿš€ Run โ€” ุชุดุบูŠู„ ุงู„ุณูŠุฑูุฑ
406
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
407
+ if __name__ == "__main__":
408
+ print("=" * 60)
409
+ print(" ๐Ÿ–ฅ๏ธ Linux System Server โ€” BU THE ZYZ STUDIO")
410
+ print(" Port: 7860")
411
+ print(" Token: Set LINUX_API_TOKEN env variable")
412
+ print("=" * 60)
413
+ app.run(host="0.0.0.0", port=7860, debug=False, threaded=True)
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
2
+ # LINUX SYSTEM SERVER โ€” requirements.txt
3
+ # ุฎุงุต ุจู€: ุณูŠุฑูุฑ 2 (ุณูŠุฑูุฑ ู†ุธุงู… Linux)
4
+ # Belongs to: SERVER 2 (Linux System Server)
5
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
6
+
7
+ flask==3.0.3
8
+ flask-cors>=4.0.0
9
+ requests>=2.31.0