2f0597c81b
Includes c2-core (FastAPI/MQTT/Firestore), discord-bot (slash commands), frontend (Next.js admin UI), and mosquitto config.
45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
from typing import Optional
|
|
from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Security
|
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
from app.internal.storage import upload_audio
|
|
from app.internal import firestore as fstore
|
|
from app.internal.logger import logger
|
|
|
|
router = APIRouter(tags=["upload"])
|
|
|
|
_bearer = HTTPBearer(auto_error=False)
|
|
|
|
|
|
@router.post("/upload")
|
|
async def upload_call_audio(
|
|
file: UploadFile = File(...),
|
|
call_id: str = Form(...),
|
|
node_id: str = Form(...),
|
|
credentials: Optional[HTTPAuthorizationCredentials] = Security(_bearer),
|
|
):
|
|
"""
|
|
Receive an audio recording from an edge node.
|
|
Upload to GCS, update the call document in Firestore with the audio URL.
|
|
"""
|
|
# Verify the per-node API key
|
|
if not credentials:
|
|
raise HTTPException(401, "Missing authorization")
|
|
key_doc = await fstore.doc_get("node_keys", node_id)
|
|
if not key_doc or key_doc.get("api_key") != credentials.credentials:
|
|
raise HTTPException(401, "Invalid node API key")
|
|
|
|
data = await file.read()
|
|
if not data:
|
|
raise HTTPException(400, "Empty file.")
|
|
|
|
filename = f"{call_id}_{file.filename}"
|
|
audio_url = await upload_audio(data, filename)
|
|
|
|
if audio_url:
|
|
try:
|
|
await fstore.doc_update("calls", call_id, {"audio_url": audio_url})
|
|
except Exception as e:
|
|
logger.warning(f"Could not update call {call_id} with audio_url: {e}")
|
|
|
|
return {"url": audio_url}
|