# app/main.py - PERMISSION ERROR TUZATILGAN VERSIYA import os import asyncio from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from app.api.routes import router as bemor_router from app.api.dispatcher_routes import router as dispatcher_router from app.services.models import load_models # 🆕 Brigade Simulator import from app.services.brigade_simulator import get_simulator from app.core.database import db # --- YECHIM UCHUN O'ZGARTIRISH --- # Barcha o'zgaruvchan (dinamik) ma'lumotlar uchun yagona papka yaratamiz. # Bu papkaga yozish uchun ruxsat bo'ladi. PERSISTENT_DIR = "persistent_storage" # Yaratilishi kerak bo'lgan papkalar yo'lini yangi asosiy papkaga nisbatan belgilaymiz TEMP_AUDIO_DIR = os.path.join(PERSISTENT_DIR, "audio") UPLOAD_DIR = os.path.join(PERSISTENT_DIR, "uploads") DATA_DIR = os.path.join(PERSISTENT_DIR, "data") # Faqat dinamik papkalarni yaratamiz os.makedirs(TEMP_AUDIO_DIR, exist_ok=True) os.makedirs(UPLOAD_DIR, exist_ok=True) os.makedirs(DATA_DIR, exist_ok=True) # ESLATMA: `static/bemor` va `static/dispatcher` uchun `os.makedirs` olib tashlandi. # Chunki bu papkalardagi `index.html` kabi fayllar sizning loyihangizda # oldindan mavjud bo'lishi kerak va ularni dastur yordamida yaratish shart emas. # ------------------------------------ # 🆕 Global simulator task simulator_task = None @asynccontextmanager async def lifespan(app: FastAPI): # Ilova ishga tushishidan oldin print("🚀 Ilova ishga tushmoqda...") print("📦 AI modellari yuklanmoqda...") load_models() print("✅ Barcha modellar tayyor!") # 🆕 Brigade simulator ishga tushirish print("🚑 Brigade simulator ishga tushmoqda...") global simulator_task simulator = get_simulator(db) simulator_task = asyncio.create_task(simulator.start()) print("✅ Brigade simulator tayyor!") yield # Ilova to'xtagandan keyin print("🛑 Ilova to'xtatilmoqda...") # 🆕 Simulator to'xtatish if simulator_task: simulator.stop() simulator_task.cancel() try: await simulator_task except asyncio.CancelledError: pass print("✅ Simulator to'xtatildi") print("👋 Ilova ishini yakunladi.") app = FastAPI( title="Help.me - Tez Tibbiy Yordam AI Tizimi", description="Bemorlardan ovozli xabarlar qabul qilib, AI tahlil qiluvchi va dispetcherlarga yuboruvchi tizim", version="1.0.0 (MVP)", lifespan=lifespan ) # Routerlarni ulash app.include_router(bemor_router) # Bemor WebSocket va APIlar app.include_router(dispatcher_router) # Dispetcher APIlar # Static fayllar # --- YECHIM UCHUN O'ZGARTIRISH --- # /audio endi yangi, yozish mumkin bo'lgan `persistent_storage/audio` papkasidan olinadi app.mount("/audio", StaticFiles(directory=TEMP_AUDIO_DIR), name="audio") # Bu qator o'zgarmaydi. U `static` papkasidagi (bemor/index.html kabi) # o'zgarmas fayllarni topish uchun kerak. app.mount("/static", StaticFiles(directory="static"), name="static") # ------------------------------------ # Bemor interfeysi (Root URL) @app.get("/", include_in_schema=False) async def read_root(): """Bemor uchun asosiy sahifa""" # Bu yo'l to'g'ri, chunki u `app.mount("/static", ...)` ga nisbatan ishlaydi return FileResponse('static/bemor/index.html') # Dispetcher paneli @app.get("/dispatcher", include_in_schema=False) async def dispatcher_panel(): """Dispetcher dashboard""" # Bu yo'l ham to'g'ri return FileResponse('static/dispatcher/index.html')