import os import uuid import json from datetime import datetime from flask import Flask, request, jsonify, send_file from flask_socketio import SocketIO, emit import base64 import io app = Flask(__name__) app.config['SECRET_KEY'] = 'messenger-secret-key' app.config['DEBUG'] = False # Настройки для production среды socketio = SocketIO( app, cors_allowed_origins="*", ping_timeout=60, ping_interval=25, logger=True, engineio_logger=False, async_mode='eventlet', max_http_buffer_size=100 * 1024 * 1024 # 100MB для больших файлов ) # Хранилища данных users = {} messages = [] voice_messages = {} active_calls = {} HTML_TEMPLATE = ''' Мобильный Мессенджер

💬

Мобильный Мессенджер

Общение, звонки, видео

💬 Мессенджер

0 пользователей онлайн
Начните общение!
Ожидание подключения...
Звонок...
00:00

Запись голосового сообщения...

Нажмите для остановки

Входящий звонок

...

''' @app.route('/') def index(): return HTML_TEMPLATE @socketio.on('connect') def handle_connect(): print(f'Client connected: {request.sid}') emit('user_list_update', { 'count': len(users), 'users': [user_data['username'] for user_data in users.values()] }) @socketio.on('disconnect') def handle_disconnect(): print(f'Client disconnected: {request.sid}') # Find and remove the disconnected user disconnected_user = None for user_id, user_data in list(users.items()): if user_data.get('sid') == request.sid: disconnected_user = user_data['username'] # End any active calls for call_id, call_data in list(active_calls.items()): if call_data['from_user'] == disconnected_user or call_data['to_user'] == disconnected_user: try: emit('call_ended', room=call_data['to_sid']) except: pass try: emit('call_ended', room=call_data['from_sid']) except: pass del active_calls[call_id] del users[user_id] break if disconnected_user: emit('user_list_update', { 'count': len(users), 'users': [user_data['username'] for user_data in users.values()] }, broadcast=True) @socketio.on('register') def handle_register(username): user_id = str(uuid.uuid4()) users[user_id] = { 'username': username, 'sid': request.sid, 'joined': datetime.now().isoformat() } emit('registration_success', { 'user_id': user_id, 'username': username }) emit('user_list_update', { 'count': len(users), 'users': [user_data['username'] for user_data in users.values()] }, broadcast=True) @socketio.on('message') def handle_message(data): message = { 'id': str(uuid.uuid4()), 'sender': data['sender'], 'text': data['text'], 'timestamp': datetime.now().isoformat() } messages.append(message) emit('new_message', message, broadcast=True) @socketio.on('voice_message') def handle_voice_message(data): try: audio_data = base64.b64decode(data['audio_data']) filename = f"voice_{uuid.uuid4()}.webm" with open(filename, 'wb') as f: f.write(audio_data) voice_data = { 'filename': filename, 'sender': data['sender'], 'duration': data.get('duration', 0), 'timestamp': datetime.now().isoformat() } voice_messages[filename] = voice_data emit('new_voice_message', voice_data, broadcast=True) except Exception as e: print(f"Error handling voice message: {e}") @socketio.on('call_request') def handle_call_request(data): target_username = data.get('to_user') target_sid = None for user_data in users.values(): if user_data['username'] == target_username: target_sid = user_data['sid'] break if target_sid: active_calls[data['call_id']] = { 'from_user': data['from_user'], 'to_user': target_username, 'from_sid': request.sid, 'to_sid': target_sid, 'is_video': data.get('isVideo', False) } emit('incoming_call', { 'call_id': data['call_id'], 'from_user': data['from_user'], 'isVideo': data.get('isVideo', False) }, room=target_sid) @socketio.on('call_answer') def handle_call_answer(data): call_id = data.get('call_id') if call_id in active_calls: call_data = active_calls[call_id] if data['answer']: emit('call_answered', { 'answer': True, 'isVideo': call_data['is_video'] }, room=call_data['from_sid']) else: emit('call_answered', { 'answer': False }, room=call_data['from_sid']) del active_calls[call_id] @socketio.on('call_end') def handle_call_end(data): call_id = data.get('call_id') if call_id in active_calls: call_data = active_calls[call_id] try: emit('call_ended', room=call_data['to_sid']) except: pass try: emit('call_ended', room=call_data['from_sid']) except: pass del active_calls[call_id] @socketio.on('webrtc_offer') def handle_webrtc_offer(data): target_username = data.get('to_user') target_sid = None for user_data in users.values(): if user_data['username'] == target_username: target_sid = user_data['sid'] break if target_sid: emit('webrtc_offer', { 'offer': data['offer'], 'from_user': data.get('from_user'), 'call_id': data.get('call_id') }, room=target_sid) @socketio.on('webrtc_answer') def handle_webrtc_answer(data): target_username = data.get('to_user') target_sid = None for user_data in users.values(): if user_data['username'] == target_username: target_sid = user_data['sid'] break if target_sid: emit('webrtc_answer', { 'answer': data['answer'], 'from_user': data.get('from_user') }, room=target_sid) @socketio.on('webrtc_ice_candidate') def handle_webrtc_ice_candidate(data): target_username = data.get('to_user') target_sid = None for user_data in users.values(): if user_data['username'] == target_username: target_sid = user_data['sid'] break if target_sid: emit('webrtc_ice_candidate', { 'candidate': data['candidate'], 'from_user': data.get('from_user') }, room=target_sid) @app.route('/voice/') def get_voice_message(filename): if filename in voice_messages: return send_file(filename, mimetype='audio/webm') return 'File not found', 404 def cleanup_temp_files(): """Очистка временных файлов""" import glob for filename in glob.glob("voice_*.webm"): try: os.remove(filename) except: pass if __name__ == '__main__': try: print("Запуск мобильного мессенджера...") print("Порт: 7860") socketio.run( app, host='0.0.0.0', port=7860, debug=False, allow_unsafe_werkzeug=True ) finally: cleanup_temp_files()