from flask import Flask, render_template, request, jsonify, session import subprocess import os import uuid import time from datetime import datetime import base64 import io import platform import socket from PIL import Image app = Flask(__name__) app.secret_key = os.urandom(24) class RemoteDesktop: def __init__(self): self.sessions = {} self.screen_quality = 80 self.screen_scale = 0.7 self.screenshot_method = None self._detect_screenshot_method() def _detect_screenshot_method(self): """Автоматическое определение доступного метода захвата экрана""" methods = [] # Проверяем системные утилиты для Ubuntu if subprocess.run(['which', 'gnome-screenshot'], capture_output=True).returncode == 0: methods.append('gnome-screenshot') if subprocess.run(['which', 'scrot'], capture_output=True).returncode == 0: methods.append('scrot') if subprocess.run(['which', 'import'], capture_output=True).returncode == 0: methods.append('imagemagick') # Проверяем Python библиотеки try: import mss methods.append('mss') except ImportError: pass print(f"📸 Доступные методы захвата экрана: {methods}") if methods: self.screenshot_method = methods[0] print(f"✅ Выбран метод: {self.screenshot_method}") else: print("❌ Не найдены методы захвата экрана") def create_session(self): session_id = str(uuid.uuid4()) self.sessions[session_id] = { 'created_at': datetime.now(), 'last_activity': datetime.now() } return session_id def get_system_info(self): """Получение информации о системе""" try: # Получаем информацию о дистрибутиве Ubuntu distro_info = "" try: with open('/etc/lsb-release', 'r') as f: for line in f: if line.startswith('DISTRIB_DESCRIPTION'): distro_info = line.split('=')[1].strip().strip('"') except: distro_info = "Ubuntu (точная версия неизвестна)" system_info = { 'distribution': distro_info, 'platform': platform.system(), 'platform_release': platform.release(), 'architecture': platform.machine(), 'hostname': socket.gethostname(), 'username': os.getenv('USER'), 'display': os.environ.get('DISPLAY', ':0'), 'screenshot_method': self.screenshot_method, 'python_version': platform.python_version(), 'current_directory': os.getcwd() } return system_info except Exception as e: return {'error': str(e)} def capture_screenshot(self): """Создание скриншота рабочего стола""" try: if not self.screenshot_method: return None, "Не найдены методы захвата экрана" if self.screenshot_method == 'gnome-screenshot': return self._capture_with_gnome_screenshot() elif self.screenshot_method == 'scrot': return self._capture_with_scrot() elif self.screenshot_method == 'imagemagick': return self._capture_with_imagemagick() elif self.screenshot_method == 'mss': return self._capture_with_mss() else: return None, f"Неизвестный метод: {self.screenshot_method}" except Exception as e: return None, f"Ошибка захвата экрана: {str(e)}" def _capture_with_gnome_screenshot(self): """Захват экрана с помощью gnome-screenshot (рекомендуется для Ubuntu)""" try: # Используем временный файл для надежности temp_file = f"/tmp/screenshot_{int(time.time())}.png" result = subprocess.run([ 'gnome-screenshot', '-f', temp_file, '--include-pointer' ], capture_output=True, text=True, timeout=10) if result.returncode != 0: return None, f"GNOME Screenshot failed: {result.stderr}" # Читаем файл with open(temp_file, 'rb') as f: img_data = f.read() # Удаляем временный файл os.unlink(temp_file) img = Image.open(io.BytesIO(img_data)) return self._encode_image(img), None except subprocess.TimeoutExpired: return None, "GNOME Screenshot timeout" except Exception as e: return None, f"GNOME Screenshot error: {str(e)}" def _capture_with_scrot(self): """Захват экрана с помощью scrot""" try: temp_file = f"/tmp/screenshot_{int(time.time())}.png" result = subprocess.run(['scrot', '-o', temp_file], capture_output=True, text=True, timeout=10) if result.returncode != 0: return None, f"Scrot failed: {result.stderr}" with open(temp_file, 'rb') as f: img_data = f.read() os.unlink(temp_file) img = Image.open(io.BytesIO(img_data)) return self._encode_image(img), None except subprocess.TimeoutExpired: return None, "Scrot timeout" except Exception as e: return None, f"Scrot error: {str(e)}" def _capture_with_imagemagick(self): """Захват экрана с помощью ImageMagick""" try: result = subprocess.run(['import', '-window', 'root', 'png:-'], capture_output=True, timeout=10) if result.returncode != 0: return None, f"ImageMagick failed: {result.stderr}" img = Image.open(io.BytesIO(result.stdout)) return self._encode_image(img), None except subprocess.TimeoutExpired: return None, "ImageMagick timeout" except Exception as e: return None, f"ImageMagick error: {str(e)}" def _capture_with_mss(self): """Захват экрана с помощью mss""" try: import mss with mss.mss() as sct: monitor = sct.monitors[1] screenshot = sct.grab(monitor) img = Image.frombytes("RGB", screenshot.size, screenshot.bgra, "raw", "BGRX") return self._encode_image(img), None except Exception as e: return None, f"MSS error: {str(e)}" def _encode_image(self, img): """Кодирование изображения в base64""" try: # Масштабирование if self.screen_scale != 1.0: new_size = (int(img.width * self.screen_scale), int(img.height * self.screen_scale)) img = img.resize(new_size, Image.Resampling.LANCZOS) buffer = io.BytesIO() img.save(buffer, format='JPEG', quality=self.screen_quality) return base64.b64encode(buffer.getvalue()).decode('utf-8') except Exception as e: raise Exception(f"Image encoding error: {str(e)}") def execute_command(self, command): """Выполнение команды в оболочке""" try: result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30) output = result.stdout if result.stderr: output += f"\nSTDERR: {result.stderr}" return output, None except subprocess.TimeoutExpired: return None, "Command timeout" except Exception as e: return None, f"Command error: {str(e)}" def send_key(self, key): """Отправка клавиши (эмуляция)""" try: # Используем xdotool для эмуляции клавиатуры result = subprocess.run(['xdotool', 'key', key], capture_output=True, text=True, timeout=10) if result.returncode == 0: return True, None else: return False, result.stderr except Exception as e: return False, f"Keyboard error: {str(e)}" def mouse_click(self, x, y, button='left'): """Клик мыши в указанных координатах""" try: # Используем xdotool для эмуляции мыши if button == 'left': click_arg = '1' elif button == 'right': click_arg = '3' else: click_arg = '1' result = subprocess.run([ 'xdotool', 'mousemove', str(x), str(y), 'click', click_arg ], capture_output=True, text=True, timeout=10) if result.returncode == 0: return True, None else: return False, result.stderr except Exception as e: return False, f"Mouse click error: {str(e)}" remote_desktop = RemoteDesktop() @app.route('/') def index(): if 'session_id' not in session: session['session_id'] = remote_desktop.create_session() system_info = remote_desktop.get_system_info() return render_template('remote_desktop.html', system_info=system_info) @app.route('/system-info') def system_info(): info = remote_desktop.get_system_info() return jsonify(info) @app.route('/screenshot') def screenshot(): """Получение скриншота""" if 'session_id' not in session: return jsonify({'error': 'Сессия не найдена'}) image_data, error = remote_desktop.capture_screenshot() if error: return jsonify({'error': error}) return jsonify({'image': image_data}) @app.route('/command', methods=['POST']) def execute_command(): """Выполнение команды""" if 'session_id' not in session: return jsonify({'error': 'Сессия не найдена'}) data = request.get_json() command = data.get('command', '').strip() if not command: return jsonify({'error': 'Пустая команда'}) output, error = remote_desktop.execute_command(command) if error: return jsonify({'error': error}) return jsonify({'output': output}) @app.route('/keyboard', methods=['POST']) def keyboard_action(): """Эмуляция клавиатуры""" if 'session_id' not in session: return jsonify({'error': 'Сессия не найдена'}) data = request.get_json() key = data.get('key', '') if not key: return jsonify({'error': 'Не указана клавиша'}) success, error = remote_desktop.send_key(key) if not success: return jsonify({'error': error}) return jsonify({'status': 'success'}) @app.route('/mouse/click', methods=['POST']) def mouse_click(): """Клик мыши""" if 'session_id' not in session: return jsonify({'error': 'Сессия не найдена'}) data = request.get_json() x = data.get('x', 0) y = data.get('y', 0) button = data.get('button', 'left') success, error = remote_desktop.mouse_click(x, y, button) if not success: return jsonify({'error': error}) return jsonify({'status': 'success'}) @app.route('/settings', methods=['POST']) def update_settings(): """Обновление настроек""" if 'session_id' not in session: return jsonify({'error': 'Сессия не найдена'}) data = request.get_json() quality = data.get('quality') scale = data.get('scale') if quality is not None: remote_desktop.screen_quality = max(10, min(100, quality)) if scale is not None: remote_desktop.screen_scale = max(0.1, min(1.0, scale)) return jsonify({ 'quality': remote_desktop.screen_quality, 'scale': remote_desktop.screen_scale }) @app.route('/test') def test_page(): """Тестовая страница""" image_data, error = remote_desktop.capture_screenshot() if error: return f"""

❌ Ошибка захвата экрана

{error}

Решение для Ubuntu:

sudo apt update
sudo apt install gnome-screenshot scrot imagemagick xdotool
pip install mss pillow
""" return f"""

✅ Тест захвата экрана - УСПЕШНО!

Метод: {remote_desktop.screenshot_method}

← Вернуться к удаленному рабочему столу

""" if __name__ == '__main__': os.makedirs('templates', exist_ok=True) with open('templates/remote_desktop.html', 'w', encoding='utf-8') as f: f.write(''' Удаленный рабочий стол Ubuntu

🖥️ Удаленный рабочий стол Ubuntu

Управление рабочим столом через веб-интерфейс

🖼️ Нажмите "Обновить экран" для захвата рабочего стола

💻 Командная строка

Статус: Готов Метод: {{ system_info.screenshot_method }} | Ubuntu
''') print("=" * 60) print("🖥️ УДАЛЕННЫЙ РАБОЧИЙ СТОЛ ДЛЯ UBUNTU") print("=" * 60) system_info = remote_desktop.get_system_info() print(f"💻 Система: {system_info.get('distribution', 'Ubuntu')}") print(f"📸 Метод захвата: {remote_desktop.screenshot_method}") if remote_desktop.screenshot_method: print("✅ Захват экрана настроен корректно") else: print("❌ Установите зависимости:") print(" sudo apt install gnome-screenshot scrot imagemagick xdotool") print("🌐 Сервер запущен: http://0.0.0.0:5000") print("🧪 Тест: http://0.0.0.0:5000/test") print("=" * 60) app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)