import eventlet eventlet.monkey_patch() import logging import os from flask import Flask, request from flask_socketio import SocketIO from flask_cors import CORS # Configure logging logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # Initialize Flask app = Flask(__name__) # Configure CORS CORS(app, resources={ r"/*": { "origins": ["http://localhost:5146", "http://127.0.0.1:5146"], "methods": ["GET", "POST"], "allow_headers": ["Content-Type"], "supports_credentials": True } }) # Initialize SocketIO socketio = SocketIO( app, cors_allowed_origins=["http://localhost:5146", "http://127.0.0.1:5146"], async_mode='eventlet', logger=True, engineio_logger=True, ping_timeout=60, ping_interval=25 ) # Store active downloads for testing active_downloads = {} download_history = {} @socketio.on('connect') def handle_connect(): logger.info(f'Client connected from {request.remote_addr}') # Log headers for debugging logger.info(f'Headers: {dict(request.headers)}') # Send current download status socketio.emit('update_status', { 'history': list(download_history.values()) }) socketio.emit('connection_status', {'status': 'connected'}) logger.info('Sent initial status to client') @socketio.on('disconnect') def handle_disconnect(): logger.info('Client disconnected') @socketio.on('search') def handle_search(data): logger.info(f'Search request received: {data}') query = data.get('query', '').strip() search_type = data.get('type', 'track') if not query: socketio.emit('search_error', {'message': 'Empty search query'}) return # Simulate search results results = { 'tracks': [ { 'id': '1', 'type': 'track', 'name': f'Test Track for "{query}"', 'artist': 'Test Artist', 'album': 'Test Album', 'url': 'http://test.com/track1', 'image': 'https://via.placeholder.com/300', 'duration': 180000 }, { 'id': '2', 'type': 'track', 'name': f'Another Track for "{query}"', 'artist': 'Another Artist', 'album': 'Another Album', 'url': 'http://test.com/track2', 'image': 'https://via.placeholder.com/300', 'duration': 240000 } ] } logger.info(f'Sending search results for query: {query}') socketio.emit('search_results', { 'query': query, 'type': search_type, 'results': results['tracks'] # Send just the tracks array }) @socketio.on('download') def handle_download(data): logger.info(f'Download request received: {data}') url = data.get('url') item_type = data.get('type') item_name = data.get('name') item_artist = data.get('artist') if not url: socketio.emit('toast', { 'title': 'Download Error', 'body': 'No URL provided' }) return download_info = { 'name': item_name, 'type': item_type, 'artist': item_artist, 'url': url, 'status': 'Downloading...', 'progress': 0 } # Store in history download_history[url] = download_info # Simulate download progress def update_progress(): progress_steps = [25, 50, 75, 100] status_messages = ['Downloading...', 'Processing...', 'Finalizing...', 'Complete'] for i, progress in enumerate(progress_steps): eventlet.sleep(2) # Simulate work download_info['progress'] = progress download_info['status'] = status_messages[i] socketio.emit('update_status', { 'history': list(download_history.values()) }) # Start progress updates in background eventlet.spawn(update_progress) @socketio.on('cancel_all') def handle_cancel_all(): logger.info('Cancelling all downloads') for url in download_history: download_history[url]['status'] = 'Cancelled' socketio.emit('update_status', { 'history': list(download_history.values()) }) @socketio.on('cancel_active') def handle_cancel_active(): logger.info('Cancelling active download') active_downloads = [url for url, info in download_history.items() if info['status'] not in ['Complete', 'Cancelled', 'Error']] if active_downloads: url = active_downloads[0] download_history[url]['status'] = 'Cancelled' socketio.emit('update_status', { 'history': list(download_history.values()) }) if __name__ == '__main__': try: logger.info("Starting test server on port 5140...") socketio.run(app, host='0.0.0.0', port=5140) except Exception as e: logger.error(f"Failed to start server: {str(e)}", exc_info=True)