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)