from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse, JSONResponse from dotenv import load_dotenv from pathlib import Path import os import requests import subprocess import time from app.auth import get_room_name load_dotenv() app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Mount the static directory app.mount("/static", StaticFiles(directory="frontend/out", html=True), name="static") def _create_room(): api_path = os.getenv("DAILY_API_PATH") or "https://api.daily.co/v1" expiry_time = os.getenv("BOT_MAX_DURATION", 300) daily_api_key = os.getenv("DAILY_API_KEY", None) try: res = requests.post( f"{api_path}/rooms", headers={"Authorization": f"Bearer {daily_api_key}"}, json={ "properties": { "exp": time.time() + int(expiry_time), "eject_at_room_exp": True, "enable_prejoin_ui": False, "start_audio_off": True, "permissions": { "canSend": ["video"] } } } ) if res.status_code != 200: return JSONResponse({ "error": "Unable to create room", "status_code": res.status_code, "text": res.text }, 500) data = res.json() print(data) return JSONResponse({"room_url": data["url"], "privacy": data["privacy"]}) except Exception: return JSONResponse({"error": Exception}) def _start_bot(bot_path, room_url, args=None): daily_room_name = get_room_name(room_url) daily_api_path = os.getenv("DAILY_API_PATH") daily_api_key = os.getenv("DAILY_API_KEY") #@TODO error handling here if args: extra_args = " ".join([f'-{x[0]} "{x[1]}"' for x in args]) else: extra_args = "" proc = subprocess.Popen( [ f"python3 {bot_path} -u {room_url} -k {daily_api_key} {extra_args}" ], shell=True, bufsize=1, ) # Don't return until the bot has joined the room, but wait for at most 2 seconds. attempts = 0 while attempts < 20: time.sleep(0.1) attempts += 1 res = requests.get( f"{daily_api_path}/rooms/{daily_room_name}/get-session-data", headers={"Authorization": f"Bearer {daily_api_key}"}, ) if res.status_code == 200: break print(f"Took {attempts} attempts to join room {daily_room_name}") return JSONResponse({"started": True}) @app.post("/start") async def start(request: Request): data = await request.json() return _start_bot("./app/bot.py", data['room_url']) @app.post("/create") async def create(): return _create_room() @app.get("/{path_name:path}", response_class=FileResponse) async def catch_all(path_name: str): if path_name == "": return FileResponse("frontend/out/index.html") file_path = Path("frontend/out") / path_name if file_path.is_file(): return file_path html_file_path = file_path.with_suffix(".html") if html_file_path.is_file(): return FileResponse(html_file_path) raise HTTPException(status_code=450, detail="Incorrect API call") # Run the application using Uvicorn if __name__ == "__main__": import uvicorn uvicorn.run( "server:app", host="0.0.0.0", port=int(os.getenv('FAST_API_PORT', 8000)), reload=os.getenv('FAST_API_RELOAD', 'false').lower() == 'true', #ssl_certfile=args.ssl_certfile, #ssl_keyfile=args.ssl_keyfile, )