from flask import Flask, render_template_string, request, redirect, url_for, session import random import string import json import os from flask_socketio import SocketIO, join_room, leave_room, emit import hashlib app = Flask(__name__) app.config['SECRET_KEY'] = 'your-very-secret-key-here' # ОЧЕНЬ ВАЖНО: смените на реальный секретный ключ! socketio = SocketIO(app) # Пути к JSON-файлам (лучше использовать абсолютные пути или пути относительно app.root_path) ROOMS_DB = os.path.join(app.root_path, 'rooms.json') USERS_DB = os.path.join(app.root_path, 'users.json') # Загрузка данных из JSON (с обработкой ошибок) def load_json(file_path, default={}): try: if os.path.exists(file_path): with open(file_path, 'r', encoding='utf-8') as f: return json.load(f) return default except (FileNotFoundError, json.JSONDecodeError) as e: print(f"Error loading JSON from {file_path}: {e}") return default # Сохранение данных в JSON (с обработкой ошибок) def save_json(file_path, data): try: with open(file_path, 'w', encoding='utf-8') as f: json.dump(data, f, indent=4, ensure_ascii=False) except OSError as e: print(f"Error saving JSON to {file_path}: {e}") # Инициализация баз данных rooms = load_json(ROOMS_DB) users = load_json(USERS_DB) # Генерация токена def generate_token(): return ''.join(random.choices(string.ascii_letters + string.digits, k=15)) # Хеширование пароля (более безопасно использовать bcrypt или scrypt) def hash_password(password): return hashlib.sha256(password.encode('utf-8')).hexdigest() # Главная страница (регистрация/вход) @app.route('/', methods=['GET', 'POST']) def index(): if 'username' in session: return redirect(url_for('dashboard')) if request.method == 'POST': action = request.form.get('action') username = request.form.get('username') password = request.form.get('password') if action == 'register': if username in users: return "Пользователь уже существует", 400 # ВАЖНО: Хешируйте пароли перед сохранением! users[username] = hash_password(password) save_json(USERS_DB, users) session['username'] = username return redirect(url_for('dashboard')) elif action == 'login': if username in users and users[username] == hash_password(password): session['username'] = username return redirect(url_for('dashboard')) return "Неверный логин или пароль", 401 return render_template_string(''' Видеоконференция

Видеоконференция

''') # Панель управления @app.route('/dashboard', methods=['GET', 'POST']) def dashboard(): if 'username' not in session: return redirect(url_for('index')) if request.method == 'POST': action = request.form.get('action') if action == 'create': token = generate_token() # Добавляем создателя комнаты как админа rooms[token] = {'users': [], 'max_users': 5, 'admin': session['username']} save_json(ROOMS_DB, rooms) return redirect(url_for('room', token=token)) elif action == 'join': token = request.form.get('token') if token in rooms and len(rooms[token]['users']) < rooms[token]['max_users']: return redirect(url_for('room', token=token)) return "Комната не найдена или переполнена", 404 return render_template_string(''' Панель управления

Добро пожаловать, {{ session['username'] }}

''', session=session) # Выход из системы @app.route('/logout', methods=['POST']) def logout(): session.pop('username', None) return redirect(url_for('index')) # Страница комнаты @app.route('/room/') def room(token): if 'username' not in session: return redirect(url_for('index')) is_admin = False # Default to False if token in rooms: is_admin = rooms[token].get('admin') == session['username'] else: return redirect(url_for('dashboard')) # Keep this here return render_template_string(''' Комната {{ token }}

Комната: {{ token }}

''', token=token, session=session, is_admin=is_admin) # WebSocket события @socketio.on('join') def handle_join(data): token = data['token'] username = data['username'] if token in rooms and len(rooms[token]['users']) < rooms[token]['max_users']: join_room(token) if username not in rooms[token]['users']: rooms[token]['users'].append(username) save_json(ROOMS_DB, rooms) emit('user_joined', {'username': username, 'users': rooms[token]['users']}, room=token) emit('init_users', {'users': rooms[token]['users']}, to=request.sid) else: # Отправляем сообщение об ошибке, если комната заполнена emit('error_message', {'message': 'Комната переполнена'}, to=request.sid) @socketio.on('leave') def handle_leave(data): token = data['token'] username = data['username'] if token in rooms and username in rooms[token]['users']: leave_room(token) rooms[token]['users'].remove(username) # Если админ выходит, комнату нужно пометить, или назначить нового админа. Простейший вариант - удалить. if rooms[token]['admin'] == username: del rooms[token] save_json(ROOMS_DB, rooms) emit('user_left', {'username': username, 'users': rooms[token]['users']}, room=token) @socketio.on('signal') def handle_signal(data): emit('signal', data, room=data['token'], skip_sid=request.sid) @socketio.on('admin_mute') def handle_admin_mute(data): token = data['token'] target_user = data['targetUser'] by_user = data['byUser'] # Кто замьютил # Проверяем, является ли отправитель админом комнаты if token in rooms and rooms[token].get('admin') == by_user: emit('admin_muted', {'targetUser': target_user}, room=token) # Отправляем событие всем в комнате if __name__ == '__main__': socketio.run(app, host='0.0.0.0', port=7860, debug=True, allow_unsafe_werkzeug=True)