Spaces:
Paused
Paused
Download app.py from test978/Cloud_VPS_Terminal: direct link, hf CLI and curl.
- Browser
- Download file 38.6 kB
-
https://huggingface.co/spaces/test978/Cloud_VPS_Terminal/resolve/main/app.py
- Command line
-
hf download hf://spaces/test978/Cloud_VPS_Terminal/app.py
-
curl -L -o app.py https://huggingface.co/spaces/test978/Cloud_VPS_Terminal/resolve/main/app.py
38.6 kB
| import gradio as gr | |
| import subprocess | |
| import os | |
| import sys | |
| import json | |
| import shutil | |
| import signal | |
| import psutil | |
| import time | |
| import threading | |
| import traceback | |
| from pathlib import Path | |
| from datetime import datetime | |
| # ===== ู ุฌูุฏ ุงูุนู ู ุงูุฑุฆูุณู ===== | |
| WORKSPACE = os.path.join(os.path.expanduser("~"), "workspace") | |
| os.makedirs(WORKSPACE, exist_ok=True) | |
| os.chdir(WORKSPACE) | |
| # ===== ุชุฎุฒูู ุงูุนู ููุงุช ุงูุฌุงุฑูุฉ ===== | |
| running_processes = {} | |
| process_lock = threading.Lock() | |
| terminal_history = [] | |
| # ===== ุชูููุฐ ุฃูุงู ุฑ ุงูุทุฑููุฉ ===== | |
| def execute_command(command, working_dir=None): | |
| """ุชูููุฐ ุฃู ุฑ ูู ุงูุทุฑููุฉ ู ุน ุฏุนู ูุงู ู""" | |
| if not command or not command.strip(): | |
| return "โ ๏ธ ุงูุชุจ ุฃู ุฑุงู ููุชูููุฐ" | |
| work_dir = working_dir if working_dir and os.path.isdir(working_dir) else WORKSPACE | |
| # ุญูุธ ูู ุงูุณุฌู | |
| timestamp = datetime.now().strftime("%H:%M:%S") | |
| terminal_history.append(f"[{timestamp}] $ {command}") | |
| try: | |
| # ุฃูุงู ุฑ ุฎุงุตุฉ | |
| cmd_parts = command.strip().split() | |
| cmd_name = cmd_parts[0] if cmd_parts else "" | |
| # ุฃู ุฑ cd | |
| if cmd_name == "cd": | |
| target = cmd_parts[1] if len(cmd_parts) > 1 else WORKSPACE | |
| if target == "~": | |
| target = WORKSPACE | |
| target_path = os.path.join(work_dir, target) if not os.path.isabs(target) else target | |
| target_path = os.path.abspath(target_path) | |
| if os.path.isdir(target_path): | |
| os.chdir(target_path) | |
| return f"๐ ุงูุชููุช ุฅูู: {target_path}" | |
| else: | |
| return f"โ ุงูู ุฌูุฏ ุบูุฑ ู ูุฌูุฏ: {target_path}" | |
| # ุฃู ุฑ clear | |
| if cmd_name in ("clear", "cls"): | |
| terminal_history.clear() | |
| return "๐งน ุชู ู ุณุญ ุงูุดุงุดุฉ" | |
| # ุชูููุฐ ุงูุฃู ุฑ | |
| env = os.environ.copy() | |
| env['PYTHONUNBUFFERED'] = '1' | |
| env['HOME'] = os.path.expanduser("~") | |
| env['PATH'] = env.get('PATH', '') + ':/usr/local/bin:/usr/bin:/bin' | |
| result = subprocess.run( | |
| command, | |
| shell=True, | |
| capture_output=True, | |
| text=True, | |
| timeout=300, | |
| cwd=work_dir, | |
| env=env, | |
| ) | |
| output_parts = [] | |
| if result.stdout: | |
| output_parts.append(result.stdout) | |
| if result.stderr: | |
| # ุจุนุถ ุงูุจุฑุงู ุฌ ุชุณุชุฎุฏู stderr ููู ุนููู ุงุช ุงูุนุงุฏูุฉ | |
| if result.returncode == 0: | |
| output_parts.append(result.stderr) | |
| else: | |
| output_parts.append(f"โ ๏ธ STDERR:\n{result.stderr}") | |
| if result.returncode != 0 and not output_parts: | |
| output_parts.append(f"โ Exit code: {result.returncode}") | |
| if not output_parts: | |
| output_parts.append("โ ุชู ุงูุชูููุฐ ุจูุฌุงุญ (ุจุฏูู ู ุฎุฑุฌุงุช)") | |
| return '\n'.join(output_parts) | |
| except subprocess.TimeoutExpired: | |
| return "โฐ ุงูุชูุช ุงูู ููุฉ (5 ุฏูุงุฆู). ุงุณุชุฎุฏู 'ุชุดุบูู ูู ุงูุฎูููุฉ' ููุนู ููุงุช ุงูุทูููุฉ." | |
| except FileNotFoundError: | |
| return f"โ ุงูุฃู ุฑ ุบูุฑ ู ูุฌูุฏ: {cmd_name}\nุฌุฑุจ: pip install ุฃู apt-get install" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| # ===== ุชุดุบูู ูู ุงูุฎูููุฉ ===== | |
| def run_background(command, working_dir=None): | |
| """ุชุดุบูู ุฃู ุฑ ูู ุงูุฎูููุฉ (ููุจูุชุงุช ูุงูุณูุฑูุฑุงุช)""" | |
| if not command or not command.strip(): | |
| return "โ ๏ธ ุงูุชุจ ุฃู ุฑุงู ููุชุดุบูู" | |
| work_dir = working_dir if working_dir and os.path.isdir(working_dir) else WORKSPACE | |
| try: | |
| env = os.environ.copy() | |
| env['PYTHONUNBUFFERED'] = '1' | |
| # ุฅูุดุงุก ู ููุงุช ููู ุฎุฑุฌุงุช | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| log_file = os.path.join(WORKSPACE, f".logs/process_{timestamp}.log") | |
| os.makedirs(os.path.dirname(log_file), exist_ok=True) | |
| log_handle = open(log_file, 'w') | |
| process = subprocess.Popen( | |
| command, | |
| shell=True, | |
| stdout=log_handle, | |
| stderr=subprocess.STDOUT, | |
| cwd=work_dir, | |
| env=env, | |
| preexec_fn=os.setsid if os.name != 'nt' else None, | |
| ) | |
| with process_lock: | |
| running_processes[process.pid] = { | |
| 'command': command, | |
| 'pid': process.pid, | |
| 'start_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
| 'log_file': log_file, | |
| 'process': process, | |
| 'log_handle': log_handle, | |
| } | |
| return ( | |
| f"โ ุชู ุงูุชุดุบูู ูู ุงูุฎูููุฉ!\n" | |
| f"{'โ' * 40}\n" | |
| f"๐ PID: {process.pid}\n" | |
| f"๐ ุงูุฃู ุฑ: {command}\n" | |
| f"๐ ู ูู ุงูุณุฌู: {log_file}\n" | |
| f"{'โ' * 40}\n" | |
| f"๐ก ูู ุชุงุจุนุฉ ุงูู ุฎุฑุฌุงุช: cat {log_file}\n" | |
| f"๐ก ูุฅููุงู ุงูุนู ููุฉ: ุงุณุชุฎุฏู ุฒุฑ ุฅุฏุงุฑุฉ ุงูุนู ููุงุช" | |
| ) | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ ูู ุงูุชุดุบูู: {str(e)}" | |
| # ===== ุฅุฏุงุฑุฉ ุงูุนู ููุงุช ===== | |
| def list_processes(): | |
| """ุนุฑุถ ุงูุนู ููุงุช ุงูุฌุงุฑูุฉ""" | |
| output_parts = ["๐ ุงูุนู ููุงุช ุงูุฌุงุฑูุฉ ูู ุงูุฎูููุฉ:", "โ" * 50] | |
| with process_lock: | |
| if not running_processes: | |
| output_parts.append("๐ญ ูุง ุชูุฌุฏ ุนู ููุงุช ุฌุงุฑูุฉ") | |
| else: | |
| for pid, info in list(running_processes.items()): | |
| proc = info['process'] | |
| status = "๐ข ูุนู ู" if proc.poll() is None else f"๐ด ุงูุชูู (code: {proc.returncode})" | |
| # ู ุนููู ุงุช ุงูุฐุงูุฑุฉ | |
| mem_info = "" | |
| try: | |
| p = psutil.Process(pid) | |
| mem = p.memory_info().rss / 1024 / 1024 | |
| cpu = p.cpu_percent() | |
| mem_info = f" ๐พ RAM: {mem:.1f}MB | CPU: {cpu:.1f}%" | |
| except: | |
| pass | |
| output_parts.append( | |
| f"\n๐ PID: {pid}\n" | |
| f" ๐ ุงูุฃู ุฑ: {info['command']}\n" | |
| f" ๐ ุจุฏุฃ: {info['start_time']}\n" | |
| f" ๐ ุงูุญุงูุฉ: {status}\n" | |
| f"{mem_info}\n" | |
| f" ๐ ุงูุณุฌู: {info['log_file']}" | |
| ) | |
| # ุนู ููุงุช ุงููุธุงู | |
| output_parts.append(f"\n{'โ' * 50}") | |
| output_parts.append("๐ ู ุนููู ุงุช ุงููุธุงู :") | |
| output_parts.append(f" ๐พ RAM: {psutil.virtual_memory().percent}% ู ุณุชุฎุฏู ") | |
| output_parts.append(f" ๐ฅ๏ธ CPU: {psutil.cpu_percent()}%") | |
| output_parts.append(f" ๐ฟ Disk: {psutil.disk_usage('/').percent}% ู ุณุชุฎุฏู ") | |
| return '\n'.join(output_parts) | |
| def stop_process(pid_str): | |
| """ุฅููุงู ุนู ููุฉ""" | |
| if not pid_str or not pid_str.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ุฑูู PID" | |
| try: | |
| pid = int(pid_str.strip()) | |
| except ValueError: | |
| return "โ PID ูุฌุจ ุฃู ูููู ุฑูู ุงู" | |
| with process_lock: | |
| if pid in running_processes: | |
| info = running_processes[pid] | |
| proc = info['process'] | |
| try: | |
| if os.name != 'nt': | |
| os.killpg(os.getpgid(pid), signal.SIGTERM) | |
| else: | |
| proc.terminate() | |
| proc.wait(timeout=5) | |
| info['log_handle'].close() | |
| del running_processes[pid] | |
| return f"โ ุชู ุฅููุงู ุงูุนู ููุฉ {pid}" | |
| except subprocess.TimeoutExpired: | |
| if os.name != 'nt': | |
| os.killpg(os.getpgid(pid), signal.SIGKILL) | |
| else: | |
| proc.kill() | |
| info['log_handle'].close() | |
| del running_processes[pid] | |
| return f"โ ๏ธ ุชู ูุชู ุงูุนู ููุฉ {pid} ุจุงูููุฉ" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| else: | |
| # ู ุญุงููุฉ ุฅููุงู ุนู ููุฉ ูุธุงู | |
| try: | |
| os.kill(pid, signal.SIGTERM) | |
| return f"โ ุชู ุฅุฑุณุงู SIGTERM ููุนู ููุฉ {pid}" | |
| except ProcessLookupError: | |
| return f"โ ุงูุนู ููุฉ {pid} ุบูุฑ ู ูุฌูุฏุฉ" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| def view_process_log(pid_str): | |
| """ุนุฑุถ ุณุฌู ุนู ููุฉ""" | |
| if not pid_str or not pid_str.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ุฑูู PID" | |
| try: | |
| pid = int(pid_str.strip()) | |
| except ValueError: | |
| return "โ PID ูุฌุจ ุฃู ูููู ุฑูู ุงู" | |
| with process_lock: | |
| if pid in running_processes: | |
| log_file = running_processes[pid]['log_file'] | |
| try: | |
| with open(log_file, 'r') as f: | |
| content = f.read() | |
| if not content: | |
| return "๐ ุงูุณุฌู ูุงุฑุบ ุญุงููุงู..." | |
| # ุขุฎุฑ 100 ุณุทุฑ | |
| lines = content.split('\n') | |
| if len(lines) > 100: | |
| return f"... (ุนุฑุถ ุขุฎุฑ 100 ุณุทุฑ ู ู {len(lines)})\n\n" + '\n'.join(lines[-100:]) | |
| return content | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ ูู ูุฑุงุกุฉ ุงูุณุฌู: {str(e)}" | |
| else: | |
| return f"โ ุงูุนู ููุฉ {pid} ุบูุฑ ู ูุฌูุฏุฉ ูู ุงููุงุฆู ุฉ" | |
| # ===== ู ุฏูุฑ ุงูู ููุงุช ===== | |
| def list_files(path=None): | |
| """ุนุฑุถ ู ุญุชููุงุช ู ุฌูุฏ""" | |
| target = path if path and os.path.isdir(path) else os.getcwd() | |
| target = os.path.abspath(target) | |
| try: | |
| items = sorted(os.listdir(target)) | |
| output_parts = [ | |
| f"๐ ุงูู ุฌูุฏ: {target}", | |
| f"{'โ' * 60}", | |
| f"{'ุงูููุน':<6} {'ุงูุญุฌู ':<12} {'ุงูุชุนุฏูู':<20} {'ุงูุงุณู '}", | |
| f"{'โ' * 60}", | |
| ] | |
| total_size = 0 | |
| dir_count = 0 | |
| file_count = 0 | |
| for item in items: | |
| full_path = os.path.join(target, item) | |
| try: | |
| stat = os.stat(full_path) | |
| mod_time = datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M") | |
| if os.path.isdir(full_path): | |
| output_parts.append(f"๐ {'<DIR>':<12} {mod_time:<20} {item}/") | |
| dir_count += 1 | |
| else: | |
| size = stat.st_size | |
| total_size += size | |
| size_str = format_size(size) | |
| # ุฃููููุฉ ุญุณุจ ููุน ุงูู ูู | |
| icon = get_file_icon(item) | |
| output_parts.append(f"{icon} {size_str:<12} {mod_time:<20} {item}") | |
| file_count += 1 | |
| except PermissionError: | |
| output_parts.append(f"๐ {'N/A':<12} {'N/A':<20} {item}") | |
| output_parts.append(f"{'โ' * 60}") | |
| output_parts.append(f"๐ {dir_count} ู ุฌูุฏุงุช | {file_count} ู ููุงุช | ุงูุญุฌู : {format_size(total_size)}") | |
| return '\n'.join(output_parts) | |
| except PermissionError: | |
| return f"๐ ูุง ููุฌุฏ ุตูุงุญูุฉ ูููุตูู ุฅูู: {target}" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| def format_size(size): | |
| """ุชูุณูู ุญุฌู ุงูู ูู""" | |
| for unit in ['B', 'KB', 'MB', 'GB']: | |
| if size < 1024: | |
| return f"{size:.1f}{unit}" | |
| size /= 1024 | |
| return f"{size:.1f}TB" | |
| def get_file_icon(filename): | |
| """ุฃููููุฉ ุญุณุจ ููุน ุงูู ูู""" | |
| ext = filename.rsplit('.', 1)[-1].lower() if '.' in filename else '' | |
| icons = { | |
| 'py': '๐', 'js': '๐', 'ts': '๐', 'html': '๐', 'css': '๐จ', | |
| 'json': '๐', 'yml': 'โ๏ธ', 'yaml': 'โ๏ธ', 'toml': 'โ๏ธ', | |
| 'md': '๐', 'txt': '๐', 'log': '๐', 'csv': '๐', | |
| 'jpg': '๐ผ๏ธ', 'png': '๐ผ๏ธ', 'gif': '๐ผ๏ธ', 'svg': '๐ผ๏ธ', | |
| 'mp3': '๐ต', 'mp4': '๐ฌ', 'zip': '๐ฆ', 'tar': '๐ฆ', | |
| 'gz': '๐ฆ', 'sh': 'โก', 'bash': 'โก', 'env': '๐', | |
| 'db': '๐๏ธ', 'sqlite': '๐๏ธ', 'sql': '๐๏ธ', | |
| 'dockerfile': '๐ณ', 'gitignore': '๐', | |
| } | |
| return icons.get(ext, '๐') | |
| def read_file(filepath): | |
| """ูุฑุงุกุฉ ู ูู""" | |
| if not filepath or not filepath.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ู ุณุงุฑ ุงูู ูู" | |
| filepath = filepath.strip() | |
| if not os.path.isabs(filepath): | |
| filepath = os.path.join(os.getcwd(), filepath) | |
| try: | |
| if not os.path.exists(filepath): | |
| return f"โ ุงูู ูู ุบูุฑ ู ูุฌูุฏ: {filepath}" | |
| size = os.path.getsize(filepath) | |
| if size > 5 * 1024 * 1024: # 5MB limit | |
| return f"โ ๏ธ ุงูู ูู ูุจูุฑ ุฌุฏุงู ({format_size(size)}). ุงุณุชุฎุฏู head ุฃู tail" | |
| # ูุญุต ุฅุฐุง ูุงู ู ูู ูุตู | |
| try: | |
| with open(filepath, 'r', encoding='utf-8') as f: | |
| content = f.read() | |
| return f"๐ {filepath} ({format_size(size)}):\n{'โ' * 40}\n{content}" | |
| except UnicodeDecodeError: | |
| return f"โ ๏ธ ูุฐุง ู ูู ุซูุงุฆู (binary) ููุง ูู ูู ุนุฑุถู ููุต. ุงูุญุฌู : {format_size(size)}" | |
| except PermissionError: | |
| return f"๐ ูุง ููุฌุฏ ุตูุงุญูุฉ ููุฑุงุกุฉ: {filepath}" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| def write_file(filepath, content): | |
| """ูุชุงุจุฉ ู ูู""" | |
| if not filepath or not filepath.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ู ุณุงุฑ ุงูู ูู" | |
| filepath = filepath.strip() | |
| if not os.path.isabs(filepath): | |
| filepath = os.path.join(os.getcwd(), filepath) | |
| try: | |
| os.makedirs(os.path.dirname(filepath), exist_ok=True) | |
| with open(filepath, 'w', encoding='utf-8') as f: | |
| f.write(content or "") | |
| size = os.path.getsize(filepath) | |
| return f"โ ุชู ุญูุธ ุงูู ูู: {filepath} ({format_size(size)})" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ ูู ุงูุญูุธ: {str(e)}" | |
| def delete_file(filepath): | |
| """ุญุฐู ู ูู ุฃู ู ุฌูุฏ""" | |
| if not filepath or not filepath.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ู ุณุงุฑ ุงูู ูู" | |
| filepath = filepath.strip() | |
| if not os.path.isabs(filepath): | |
| filepath = os.path.join(os.getcwd(), filepath) | |
| try: | |
| if not os.path.exists(filepath): | |
| return f"โ ุบูุฑ ู ูุฌูุฏ: {filepath}" | |
| if os.path.isdir(filepath): | |
| shutil.rmtree(filepath) | |
| return f"โ ุชู ุญุฐู ุงูู ุฌูุฏ: {filepath}" | |
| else: | |
| os.remove(filepath) | |
| return f"โ ุชู ุญุฐู ุงูู ูู: {filepath}" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| def create_directory(dirpath): | |
| """ุฅูุดุงุก ู ุฌูุฏ""" | |
| if not dirpath or not dirpath.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ู ุณุงุฑ ุงูู ุฌูุฏ" | |
| dirpath = dirpath.strip() | |
| if not os.path.isabs(dirpath): | |
| dirpath = os.path.join(os.getcwd(), dirpath) | |
| try: | |
| os.makedirs(dirpath, exist_ok=True) | |
| return f"โ ุชู ุฅูุดุงุก ุงูู ุฌูุฏ: {dirpath}" | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| def upload_file(file): | |
| """ุฑูุน ู ูู""" | |
| if file is None: | |
| return "โ ๏ธ ุงุฎุชุฑ ู ููุงู ููุฑูุน", list_files() | |
| try: | |
| filename = os.path.basename(file.name) if hasattr(file, 'name') else "uploaded_file" | |
| dest = os.path.join(os.getcwd(), filename) | |
| if isinstance(file, str): | |
| shutil.copy2(file, dest) | |
| else: | |
| shutil.copy2(file.name, dest) | |
| size = os.path.getsize(dest) | |
| return f"โ ุชู ุฑูุน: {filename} ({format_size(size)})", list_files() | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ ูู ุงูุฑูุน: {str(e)}", list_files() | |
| # ===== ู ุญุฑุฑ ุงูุฃููุงุฏ ===== | |
| def save_and_run(filepath, code): | |
| """ุญูุธ ูุชุดุบูู ู ูู""" | |
| if not filepath or not filepath.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ุงุณู ุงูู ูู", "" | |
| filepath = filepath.strip() | |
| if not os.path.isabs(filepath): | |
| filepath = os.path.join(os.getcwd(), filepath) | |
| # ุญูุธ | |
| save_result = write_file(filepath, code) | |
| # ุชุดุบูู ุญุณุจ ููุน ุงูู ูู | |
| ext = filepath.rsplit('.', 1)[-1].lower() if '.' in filepath else '' | |
| run_commands = { | |
| 'py': f'python3 "{filepath}"', | |
| 'js': f'node "{filepath}"', | |
| 'sh': f'bash "{filepath}"', | |
| 'bash': f'bash "{filepath}"', | |
| } | |
| if ext in run_commands: | |
| run_result = execute_command(run_commands[ext]) | |
| return save_result, run_result | |
| else: | |
| return save_result, "โน๏ธ ุชู ุงูุญูุธ ููุท (ููุน ุงูู ูู ูุง ูุฏุนู ุงูุชุดุบูู ุงูู ุจุงุดุฑ)" | |
| # ===== ุชุซุจูุช ุงูุญุฒู ===== | |
| def install_package(package_name): | |
| """ุชุซุจูุช ุญุฒู ุฉ ุจุงูุซูู""" | |
| if not package_name or not package_name.strip(): | |
| return "โ ๏ธ ุฃุฏุฎู ุงุณู ุงูุญุฒู ุฉ" | |
| return execute_command(f"pip install {package_name.strip()}") | |
| def system_info(): | |
| """ู ุนููู ุงุช ุงููุธุงู """ | |
| try: | |
| mem = psutil.virtual_memory() | |
| disk = psutil.disk_usage('/') | |
| cpu_count = psutil.cpu_count() | |
| boot_time = datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S") | |
| info = f""" | |
| โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| โ ๐ฅ๏ธ ู ุนููู ุงุช ุงููุธุงู โ | |
| โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ | |
| โ โ | |
| โ ๐ Python: {sys.version.split()[0]:<28}โ | |
| โ ๐ป OS: {os.uname().sysname} {os.uname().release[:20]:<20}โ | |
| โ ๐๏ธ Arch: {os.uname().machine:<28}โ | |
| โ ๐ Boot: {boot_time:<28}โ | |
| โ โ | |
| โ ๐ฅ๏ธ CPU Cores: {cpu_count:<25}โ | |
| โ ๐ CPU Usage: {psutil.cpu_percent():.1f}%{'':<23}โ | |
| โ โ | |
| โ ๐พ RAM Total: {format_size(mem.total):<25}โ | |
| โ ๐พ RAM Used: {format_size(mem.used)} ({mem.percent}%){'':<14}โ | |
| โ ๐พ RAM Free: {format_size(mem.available):<25}โ | |
| โ โ | |
| โ ๐ฟ Disk Total: {format_size(disk.total):<24}โ | |
| โ ๐ฟ Disk Used: {format_size(disk.used)} ({disk.percent}%){'':<13}โ | |
| โ ๐ฟ Disk Free: {format_size(disk.free):<24}โ | |
| โ โ | |
| โ ๐ CWD: {os.getcwd()[:30]:<30}โ | |
| โ ๐ค User: {os.environ.get('USER', 'N/A'):<29}โ | |
| โ โ | |
| โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| """ | |
| return info | |
| except Exception as e: | |
| return f"โ ุฎุทุฃ: {str(e)}" | |
| # ===== ุงููุงุฌูุฉ ===== | |
| CUSTOM_CSS = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&family=Tajawal:wght@400;500;700&display=swap'); | |
| * { font-family: 'Tajawal', sans-serif !important; } | |
| .terminal-output textarea, | |
| .code-editor textarea { | |
| font-family: 'Fira Code', 'Courier New', monospace !important; | |
| font-size: 13px !important; | |
| line-height: 1.5 !important; | |
| } | |
| .terminal-output textarea { | |
| background-color: #0d1117 !important; | |
| color: #58a6ff !important; | |
| border: 2px solid #30363d !important; | |
| } | |
| .header-banner { | |
| text-align: center; | |
| background: linear-gradient(135deg, #0d1117 0%, #161b22 50%, #0d1117 100%); | |
| padding: 20px; | |
| border-radius: 16px; | |
| margin-bottom: 15px; | |
| border: 1px solid #30363d; | |
| } | |
| .header-banner h1 { | |
| color: #58a6ff; | |
| font-size: 2.2em; | |
| margin: 0; | |
| } | |
| .header-banner p { | |
| color: #8b949e; | |
| margin: 5px 0 0; | |
| } | |
| .status-bar { | |
| background: #161b22; | |
| color: #58a6ff; | |
| padding: 8px 16px; | |
| border-radius: 8px; | |
| font-family: 'Fira Code', monospace !important; | |
| font-size: 12px; | |
| border: 1px solid #30363d; | |
| } | |
| footer { display: none !important; } | |
| """ | |
| with gr.Blocks( | |
| css=CUSTOM_CSS, | |
| title="๐ฅ๏ธ Cloud VPS Terminal", | |
| theme=gr.themes.Base( | |
| primary_hue="blue", | |
| secondary_hue="purple", | |
| neutral_hue="gray", | |
| font=gr.themes.GoogleFont("Tajawal"), | |
| ) | |
| ) as app: | |
| gr.HTML(""" | |
| <div class="header-banner"> | |
| <h1>๐ฅ๏ธ Cloud VPS Terminal</h1> | |
| <p>ูุธุงู VPS ุณุญุงุจู ูุงู ู - ุทุฑููุฉ + ู ุฏูุฑ ู ููุงุช + ู ุญุฑุฑ ุฃููุงุฏ + ุฅุฏุงุฑุฉ ุนู ููุงุช</p> | |
| </div> | |
| """) | |
| with gr.Tabs(): | |
| # โโโโโโโโโโโ ุชุงุจ ุงูุทุฑููุฉ โโโโโโโโโโโ | |
| with gr.TabItem("โก Terminal"): | |
| gr.HTML('<div class="status-bar">๐ Terminal | ุงูุชุจ ุฃู ุฃู ุฑ Linux ูุดุบููู</div>') | |
| with gr.Row(): | |
| with gr.Column(scale=4): | |
| cmd_input = gr.Textbox( | |
| label="๐ป ุงูุฃู ุฑ", | |
| placeholder="ุงูุชุจ ุฃู ุฑ Linux ููุง... ู ุซู: ls -la, pip install requests, python bot.py", | |
| lines=1, | |
| ) | |
| with gr.Column(scale=1): | |
| work_dir = gr.Textbox( | |
| label="๐ ู ุฌูุฏ ุงูุนู ู", | |
| value=WORKSPACE, | |
| lines=1, | |
| ) | |
| with gr.Row(): | |
| run_cmd_btn = gr.Button("โถ๏ธ ุชูููุฐ", variant="primary", size="lg") | |
| bg_run_btn = gr.Button("๐ ุชุดุบูู ูู ุงูุฎูููุฉ", variant="secondary", size="lg") | |
| sys_info_btn = gr.Button("โน๏ธ ู ุนููู ุงุช ุงููุธุงู ", size="lg") | |
| terminal_output = gr.Textbox( | |
| label="๐บ ุงูู ุฎุฑุฌุงุช", | |
| lines=25, | |
| max_lines=50, | |
| interactive=False, | |
| elem_classes=["terminal-output"], | |
| ) | |
| gr.HTML("<h4>โก ุฃูุงู ุฑ ุณุฑูุนุฉ:</h4>") | |
| with gr.Row(): | |
| gr.Button("๐ ls -la").click(fn=lambda: execute_command("ls -la"), outputs=[terminal_output]) | |
| gr.Button("๐ pwd").click(fn=lambda: execute_command("pwd"), outputs=[terminal_output]) | |
| gr.Button("๐พ df -h").click(fn=lambda: execute_command("df -h"), outputs=[terminal_output]) | |
| gr.Button("๐ pip list").click(fn=lambda: execute_command("pip list"), outputs=[terminal_output]) | |
| gr.Button("๐ก curl ifconfig.me").click(fn=lambda: execute_command("curl -s ifconfig.me"), outputs=[terminal_output]) | |
| gr.Button("๐ top (snapshot)").click(fn=lambda: execute_command("ps aux --sort=-%mem | head -20"), outputs=[terminal_output]) | |
| # ุฑุจุท ุงูุฃุญุฏุงุซ | |
| run_cmd_btn.click(fn=execute_command, inputs=[cmd_input, work_dir], outputs=[terminal_output]) | |
| cmd_input.submit(fn=execute_command, inputs=[cmd_input, work_dir], outputs=[terminal_output]) | |
| bg_run_btn.click(fn=run_background, inputs=[cmd_input, work_dir], outputs=[terminal_output]) | |
| sys_info_btn.click(fn=system_info, outputs=[terminal_output]) | |
| # โโโโโโโโโโโ ุชุงุจ ู ุฏูุฑ ุงูู ููุงุช โโโโโโโโโโโ | |
| with gr.TabItem("๐ File Manager"): | |
| gr.HTML('<div class="status-bar">๐ File Manager | ุฅุฏุงุฑุฉ ูุงู ูุฉ ููู ููุงุช ูุงูู ุฌูุฏุงุช</div>') | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| browse_path = gr.Textbox(label="๐ ุงูู ุณุงุฑ", value=WORKSPACE, lines=1) | |
| browse_btn = gr.Button("๐ ุงุณุชุนุฑุงุถ", variant="primary") | |
| file_list_output = gr.Textbox( | |
| label="๐ ู ุญุชููุงุช ุงูู ุฌูุฏ", | |
| lines=20, | |
| interactive=False, | |
| elem_classes=["terminal-output"], | |
| ) | |
| with gr.Column(scale=2): | |
| with gr.Tabs(): | |
| with gr.TabItem("๐ ูุฑุงุกุฉ ู ูู"): | |
| read_path = gr.Textbox(label="ู ุณุงุฑ ุงูู ูู", lines=1) | |
| read_btn = gr.Button("๐ ูุฑุงุกุฉ", variant="primary") | |
| file_content = gr.Textbox(label="ุงูู ุญุชูู", lines=15, interactive=False) | |
| with gr.TabItem("โ๏ธ ุฅูุดุงุก/ุชุนุฏูู"): | |
| new_file_path = gr.Textbox(label="ู ุณุงุฑ ุงูู ูู", lines=1, placeholder="ู ุซุงู: bot.py") | |
| new_file_content = gr.Code(label="ุงูู ุญุชูู", language="python", lines=12) | |
| save_btn = gr.Button("๐พ ุญูุธ", variant="primary") | |
| save_status = gr.Textbox(label="ุงูุญุงูุฉ", lines=2, interactive=False) | |
| with gr.TabItem("๐ ู ุฌูุฏ ุฌุฏูุฏ"): | |
| new_dir_path = gr.Textbox(label="ู ุณุงุฑ ุงูู ุฌูุฏ", lines=1) | |
| mkdir_btn = gr.Button("๐ ุฅูุดุงุก", variant="primary") | |
| mkdir_status = gr.Textbox(label="ุงูุญุงูุฉ", lines=2, interactive=False) | |
| with gr.TabItem("๐๏ธ ุญุฐู"): | |
| del_path = gr.Textbox(label="ู ุณุงุฑ ุงูู ูู/ุงูู ุฌูุฏ", lines=1) | |
| del_btn = gr.Button("๐๏ธ ุญุฐู", variant="stop") | |
| del_status = gr.Textbox(label="ุงูุญุงูุฉ", lines=2, interactive=False) | |
| with gr.TabItem("๐ค ุฑูุน ู ูู"): | |
| upload_input = gr.File(label="ุงุฎุชุฑ ู ููุงู", file_count="single") | |
| upload_btn = gr.Button("๐ค ุฑูุน", variant="primary") | |
| upload_status = gr.Textbox(label="ุงูุญุงูุฉ", lines=2, interactive=False) | |
| # ุฑุจุท ุฃุญุฏุงุซ ู ุฏูุฑ ุงูู ููุงุช | |
| browse_btn.click(fn=list_files, inputs=[browse_path], outputs=[file_list_output]) | |
| browse_path.submit(fn=list_files, inputs=[browse_path], outputs=[file_list_output]) | |
| read_btn.click(fn=read_file, inputs=[read_path], outputs=[file_content]) | |
| save_btn.click(fn=write_file, inputs=[new_file_path, new_file_content], outputs=[save_status]) | |
| mkdir_btn.click(fn=create_directory, inputs=[new_dir_path], outputs=[mkdir_status]) | |
| del_btn.click(fn=delete_file, inputs=[del_path], outputs=[del_status]) | |
| upload_btn.click(fn=upload_file, inputs=[upload_input], outputs=[upload_status, file_list_output]) | |
| # โโโโโโโโโโโ ุชุงุจ ู ุญุฑุฑ ุงูุฃููุงุฏ โโโโโโโโโโโ | |
| with gr.TabItem("โ๏ธ Code Editor"): | |
| gr.HTML('<div class="status-bar">โ๏ธ Code Editor | ูุชุงุจุฉ ูุชุดุบูู ุงูุฃููุงุฏ ู ุจุงุดุฑุฉ</div>') | |
| with gr.Row(): | |
| editor_filepath = gr.Textbox( | |
| label="๐ ุงุณู ุงูู ูู", | |
| value="script.py", | |
| lines=1, | |
| scale=2, | |
| ) | |
| editor_lang = gr.Dropdown( | |
| label="๐ ุงููุบุฉ", | |
| choices=["python", "javascript", "shell", "json", "yaml", "markdown", "html", "css"], | |
| value="python", | |
| scale=1, | |
| ) | |
| with gr.Row(): | |
| load_file_btn = gr.Button("๐ ุชุญู ูู ู ู ู ูู", variant="secondary") | |
| save_file_btn = gr.Button("๐พ ุญูุธ", variant="primary") | |
| save_run_btn = gr.Button("โถ๏ธ ุญูุธ ูุชุดุบูู", variant="primary") | |
| code_editor = gr.Code( | |
| label="โ๏ธ ุงูููุฏ", | |
| language="python", | |
| lines=25, | |
| value='# ุงูุชุจ ุงูููุฏ ููุง\nprint("ู ุฑุญุจุงู! ๐")', | |
| ) | |
| editor_output = gr.Textbox( | |
| label="๐ค ุงูู ุฎุฑุฌุงุช", | |
| lines=12, | |
| interactive=False, | |
| elem_classes=["terminal-output"], | |
| ) | |
| # ููุงูุจ ุฌุงูุฒุฉ | |
| gr.HTML("<h4>๐ฆ ููุงูุจ ุฌุงูุฒุฉ:</h4>") | |
| with gr.Row(): | |
| def template_telegram_bot(): | |
| return """# Telegram Bot Template | |
| # pip install python-telegram-bot | |
| import asyncio | |
| from telegram import Update | |
| from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes | |
| TOKEN = "YOUR_BOT_TOKEN_HERE" | |
| async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): | |
| await update.message.reply_text("ู ุฑุญุจุงู! ุฃูุง ุจูุช ุชูุฌุฑุงู ๐ค") | |
| async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE): | |
| text = update.message.text | |
| await update.message.reply_text(f"ููุช: {text}") | |
| def main(): | |
| app = Application.builder().token(TOKEN).build() | |
| app.add_handler(CommandHandler("start", start)) | |
| app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message)) | |
| print("๐ค ุงูุจูุช ูุนู ู...") | |
| app.run_polling() | |
| if __name__ == "__main__": | |
| main() | |
| """, "telegram_bot.py" | |
| def template_flask_server(): | |
| return """# Flask Web Server | |
| # pip install flask | |
| from flask import Flask, jsonify, request | |
| app = Flask(__name__) | |
| @app.route('/') | |
| def home(): | |
| return jsonify({"message": "ู ุฑุญุจุงู ุจุงูุนุงูู ! ๐", "status": "running"}) | |
| @app.route('/api/hello/<name>') | |
| def hello(name): | |
| return jsonify({"message": f"ู ุฑุญุจุงู {name}! ๐"}) | |
| if __name__ == '__main__': | |
| app.run(host='0.0.0.0', port=5000) | |
| """, "server.py" | |
| def template_discord_bot(): | |
| return """# Discord Bot Template | |
| # pip install discord.py | |
| import discord | |
| from discord.ext import commands | |
| TOKEN = "YOUR_DISCORD_TOKEN_HERE" | |
| bot = commands.Bot(command_prefix="!", intents=discord.Intents.all()) | |
| @bot.event | |
| async def on_ready(): | |
| print(f"๐ค Bot is ready: {bot.user}") | |
| @bot.command() | |
| async def hello(ctx): | |
| await ctx.send(f"ู ุฑุญุจุงู {ctx.author.name}! ๐") | |
| @bot.command() | |
| async def ping(ctx): | |
| await ctx.send(f"๐ Pong! {round(bot.latency * 1000)}ms") | |
| bot.run(TOKEN) | |
| """, "discord_bot.py" | |
| def template_scraper(): | |
| return """# Web Scraper Template | |
| # pip install requests beautifulsoup4 | |
| import requests | |
| from bs4 import BeautifulSoup | |
| import json | |
| def scrape_website(url): | |
| print(f"๐ ุฌุงุฑู ุฌูุจ: {url}") | |
| headers = {'User-Agent': 'Mozilla/5.0'} | |
| response = requests.get(url, headers=headers, timeout=10) | |
| response.raise_for_status() | |
| soup = BeautifulSoup(response.text, 'html.parser') | |
| title = soup.title.string if soup.title else "N/A" | |
| links = [a.get('href') for a in soup.find_all('a', href=True)] | |
| print(f"๐ ุงูุนููุงู: {title}") | |
| print(f"๐ ุนุฏุฏ ุงูุฑูุงุจุท: {len(links)}") | |
| return { | |
| 'title': title, | |
| 'links_count': len(links), | |
| 'links': links[:10] | |
| } | |
| if __name__ == '__main__': | |
| result = scrape_website("https://example.com") | |
| print(json.dumps(result, indent=2, ensure_ascii=False)) | |
| """, "scraper.py" | |
| tg_btn = gr.Button("๐ค ุจูุช ุชูุฌุฑุงู ") | |
| flask_btn = gr.Button("๐ Flask Server") | |
| discord_btn = gr.Button("๐ฎ ุจูุช ุฏูุณููุฑุฏ") | |
| scraper_btn = gr.Button("๐ Web Scraper") | |
| # ุฑุจุท ุงูููุงูุจ | |
| tg_btn.click(fn=template_telegram_bot, outputs=[code_editor, editor_filepath]) | |
| flask_btn.click(fn=template_flask_server, outputs=[code_editor, editor_filepath]) | |
| discord_btn.click(fn=template_discord_bot, outputs=[code_editor, editor_filepath]) | |
| scraper_btn.click(fn=template_scraper, outputs=[code_editor, editor_filepath]) | |
| # ุฑุจุท ุฃุญุฏุงุซ ุงูู ุญุฑุฑ | |
| def load_file_to_editor(filepath): | |
| if not filepath: | |
| return "โ ๏ธ ุฃุฏุฎู ู ุณุงุฑ ุงูู ูู", "" | |
| content = read_file(filepath) | |
| if content.startswith("โ") or content.startswith("โ ๏ธ") or content.startswith("๐"): | |
| return content, "" | |
| # ุฅุฒุงูุฉ ุงูุณุทุฑ ุงูุฃูู (ู ุนููู ุงุช ุงูู ูู) | |
| lines = content.split('\n') | |
| if lines and lines[0].startswith("๐"): | |
| actual_content = '\n'.join(lines[2:]) # ุชุฌุงูุฒ ุงูุณุทุฑ ุงูุฃูู ูุงููุงุตู | |
| return "โ ุชู ุงูุชุญู ูู", actual_content | |
| return "โ ุชู ุงูุชุญู ูู", content | |
| load_file_btn.click( | |
| fn=load_file_to_editor, | |
| inputs=[editor_filepath], | |
| outputs=[editor_output, code_editor] | |
| ) | |
| save_file_btn.click( | |
| fn=write_file, | |
| inputs=[editor_filepath, code_editor], | |
| outputs=[editor_output] | |
| ) | |
| save_run_btn.click( | |
| fn=save_and_run, | |
| inputs=[editor_filepath, code_editor], | |
| outputs=[editor_output, editor_output] | |
| ) | |
| # โโโโโโโโโโโ ุชุงุจ ุฅุฏุงุฑุฉ ุงูุนู ููุงุช โโโโโโโโโโโ | |
| with gr.TabItem("๐ Processes"): | |
| gr.HTML('<div class="status-bar">๐ Process Manager | ุฅุฏุงุฑุฉ ุงูุนู ููุงุช ุงูุฌุงุฑูุฉ</div>') | |
| with gr.Row(): | |
| refresh_proc_btn = gr.Button("๐ ุชุญุฏูุซ", variant="primary", size="lg") | |
| list_all_btn = gr.Button("๐ ูู ุนู ููุงุช ุงููุธุงู ", size="lg") | |
| processes_output = gr.Textbox( | |
| label="๐ ุงูุนู ููุงุช", | |
| lines=20, | |
| interactive=False, | |
| elem_classes=["terminal-output"], | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| pid_input = gr.Textbox(label="๐ข ุฑูู PID", lines=1) | |
| with gr.Row(): | |
| stop_btn = gr.Button("โน๏ธ ุฅููุงู", variant="stop") | |
| log_btn = gr.Button("๐ ุนุฑุถ ุงูุณุฌู", variant="secondary") | |
| with gr.Column(): | |
| proc_action_output = gr.Textbox( | |
| label="๐ ุงููุชูุฌุฉ", | |
| lines=10, | |
| interactive=False, | |
| elem_classes=["terminal-output"], | |
| ) | |
| # ุฑุจุท ุงูุฃุญุฏุงุซ | |
| refresh_proc_btn.click(fn=list_processes, outputs=[processes_output]) | |
| list_all_btn.click( | |
| fn=lambda: execute_command("ps aux --sort=-%mem | head -30"), | |
| outputs=[processes_output] | |
| ) | |
| stop_btn.click(fn=stop_process, inputs=[pid_input], outputs=[proc_action_output]) | |
| log_btn.click(fn=view_process_log, inputs=[pid_input], outputs=[proc_action_output]) | |
| # โโโโโโโโโโโ ุชุงุจ ุงูุญุฒู โโโโโโโโโโโ | |
| with gr.TabItem("๐ฆ Packages"): | |
| gr.HTML('<div class="status-bar">๐ฆ Package Manager | ุชุซุจูุช ูุฅุฏุงุฑุฉ ุงูุญุฒู </div>') | |
| with gr.Row(): | |
| pkg_input = gr.Textbox( | |
| label="๐ฆ ุงุณู ุงูุญุฒู ุฉ", | |
| placeholder="ู ุซุงู: requests ุฃู flask ุฃู python-telegram-bot", | |
| lines=1, | |
| scale=3, | |
| ) | |
| install_btn = gr.Button("๐ฅ ุชุซุจูุช", variant="primary", scale=1, size="lg") | |
| pkg_output = gr.Textbox( | |
| label="๐ ุงููุชูุฌุฉ", | |
| lines=15, | |
| interactive=False, | |
| elem_classes=["terminal-output"], | |
| ) | |
| gr.HTML("<h4>๐ฆ ุญุฒู ุดุงุฆุนุฉ - ุงุถุบุท ููุชุซุจูุช:</h4>") | |
| with gr.Row(): | |
| gr.Button("๐ค python-telegram-bot").click( | |
| fn=lambda: install_package("python-telegram-bot"), outputs=[pkg_output]) | |
| gr.Button("๐ flask").click( | |
| fn=lambda: install_package("flask"), outputs=[pkg_output]) | |
| gr.Button("๐ก requests").click( | |
| fn=lambda: install_package("requests"), outputs=[pkg_output]) | |
| gr.Button("๐ฎ discord.py").click( | |
| fn=lambda: install_package("discord.py"), outputs=[pkg_output]) | |
| with gr.Row(): | |
| gr.Button("๐๏ธ sqlalchemy").click( | |
| fn=lambda: install_package("sqlalchemy"), outputs=[pkg_output]) | |
| gr.Button("๐ beautifulsoup4").click( | |
| fn=lambda: install_package("beautifulsoup4"), outputs=[pkg_output]) | |
| gr.Button("๐ pandas").click( | |
| fn=lambda: install_package("pandas"), outputs=[pkg_output]) | |
| gr.Button("๐ง aiohttp").click( | |
| fn=lambda: install_package("aiohttp"), outputs=[pkg_output]) | |
| with gr.Row(): | |
| gr.Button("๐ ุนุฑุถ ุงูุญุฒู ุงูู ุซุจุชุฉ").click( | |
| fn=lambda: execute_command("pip list --format=columns"), outputs=[pkg_output]) | |
| gr.Button("๐ ุชุญุฏูุซ pip").click( | |
| fn=lambda: execute_command("pip install --upgrade pip"), outputs=[pkg_output]) | |
| install_btn.click(fn=install_package, inputs=[pkg_input], outputs=[pkg_output]) | |
| pkg_input.submit(fn=install_package, inputs=[pkg_input], outputs=[pkg_output]) | |
| gr.HTML(""" | |
| <div style="text-align:center; padding:10px; color:#8b949e; font-size:0.8em; margin-top:10px;"> | |
| ๐ฅ๏ธ Cloud VPS Terminal | โก Powered by ู ุญู ุฏ ุนูู | |
| </div> | |
| """) | |
| if __name__ == "__main__": | |
| app.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| ) |