import os from flask import Flask, send_from_directory from flask_cors import CORS from flask_migrate import Migrate from flask_socketio import SocketIO from backend.models import db from backend.config import config # Initialize extensions migrate = Migrate() socketio = SocketIO(cors_allowed_origins="*", async_mode='eventlet') def create_app(config_name=None): """Flask application factory""" if config_name is None: config_name = os.environ.get('FLASK_ENV', 'development') app = Flask(__name__, static_folder='static', static_url_path='/static') # Load configuration app.config.from_object(config[config_name]) # Configure session for OAuth state management app.config['SESSION_COOKIE_SAMESITE'] = 'Lax' # Allow cross-site on redirects app.config['SESSION_COOKIE_HTTPONLY'] = True # Ensure required directories exist os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) os.makedirs(app.config['AUDIO_FOLDER'], exist_ok=True) # Ensure database instance directory exists db_path = app.config['SQLALCHEMY_DATABASE_URI'].replace('sqlite:///', '') if db_path and db_path != ':memory:': os.makedirs(os.path.dirname(db_path), exist_ok=True) # Initialize extensions db.init_app(app) migrate.init_app(app, db) socketio.init_app(app) CORS(app, resources={r"/api/*": {"origins": app.config['CORS_ORIGINS']}}, supports_credentials=True) # Initialize OAuth/OIDC from backend.auth import init_oauth init_oauth(app) # Register blueprints from backend.routes import questions, games, teams, admin, categories, download_jobs, auth app.register_blueprint(auth.bp) app.register_blueprint(questions.bp) app.register_blueprint(games.bp) app.register_blueprint(teams.bp) app.register_blueprint(admin.bp) app.register_blueprint(categories.bp) app.register_blueprint(download_jobs.bp) # Register socket events from backend.sockets import events # Serve React frontend in production @app.route('/', defaults={'path': ''}) @app.route('/') def serve_frontend(path): """Serve React frontend""" if path and os.path.exists(os.path.join(app.static_folder, path)): return send_from_directory(app.static_folder, path) elif path.startswith('api/'): # API routes should 404 if not found return {'error': 'Not found'}, 404 else: # Serve index.html for all other routes (React Router) index_path = os.path.join(app.static_folder, 'index.html') if os.path.exists(index_path): return send_from_directory(app.static_folder, 'index.html') else: return {'message': 'Trivia Game API', 'status': 'running'}, 200 # Health check endpoint @app.route('/api/health') def health_check(): """Health check endpoint""" return {'status': 'ok', 'message': 'Trivia Game API is running'}, 200 return app