import os import click from datetime import timedelta from flask import Flask from dotenv import load_dotenv from flask_migrate import Migrate from flask_jwt_extended import JWTManager from flask_cors import CORS from models import db, bcrypt, User from celery_app import celery # Import celery instance def create_app(): """Application Factory Pattern""" load_dotenv() app = Flask(__name__) # --- Configuration --- app.config.from_mapping( SQLALCHEMY_DATABASE_URI=os.environ.get('DATABASE_URL'), SQLALCHEMY_ENGINE_OPTIONS={'pool_recycle': 3600}, JWT_SECRET_KEY=os.environ.get('JWT_SECRET_KEY'), SQLALCHEMY_TRACK_MODIFICATIONS=False, JWT_ACCESS_TOKEN_EXPIRES=timedelta(days=3), CELERY_BROKER_URL=os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0'), CELERY_RESULT_BACKEND=os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0'), DIFY_API_BASE_URL=os.environ.get("DIFY_API_BASE_URL"), DIFY_STT_API_KEY=os.environ.get("DIFY_STT_API_KEY"), DIFY_TRANSLATOR_API_KEY=os.environ.get("DIFY_TRANSLATOR_API_KEY"), DIFY_SUMMARIZER_API_KEY=os.environ.get("DIFY_SUMMARIZER_API_KEY"), DIFY_ACTION_EXTRACTOR_API_KEY=os.environ.get("DIFY_ACTION_EXTRACTOR_API_KEY") ) project_root = os.path.dirname(os.path.abspath(__file__)) UPLOAD_FOLDER = os.path.join(project_root, 'uploads') if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 1024 # 1GB upload limit # --- Initialize Extensions --- db.init_app(app) bcrypt.init_app(app) Migrate(app, db) JWTManager(app) CORS(app) # --- Configure Celery --- celery.conf.update(app.config) # This custom Task class ensures tasks run with the Flask app context class ContextTask(celery.Task): def __call__(self, *args, **kwargs): with app.app_context(): return self.run(*args, **kwargs) celery.Task = ContextTask # --- Import and Register Blueprints --- from api_routes import api_bp from ai_routes import ai_bp from action_item_routes import action_bp app.register_blueprint(api_bp) app.register_blueprint(ai_bp) app.register_blueprint(action_bp) # --- Root Route --- @app.route('/') def index(): return "AI Meeting Assistant Backend is running." # --- CLI Commands --- @app.cli.command("create_admin") @click.argument("username") @click.argument("password") def create_admin(username, password): """Creates a new admin user.""" with app.app_context(): try: if User.query.filter_by(username=username).first(): print(f"Error: User '{username}' already exists.") return admin_user = User(username=username, role='admin') admin_user.set_password(password) db.session.add(admin_user) db.session.commit() print(f"Admin user '{username}' created successfully.") except Exception as e: db.session.rollback() print(f"An error occurred: {e}") return app app = create_app() if __name__ == '__main__': port = int(os.environ.get("FLASK_RUN_PORT", 5000)) app.run(host='0.0.0.0', port=port, debug=True)