Spaces:
Sleeping
Sleeping
File size: 6,880 Bytes
a162c90 ca78935 c71e312 ca78935 c71e312 a162c90 c71e312 14279a0 0f7804c c71e312 a162c90 c71e312 a162c90 c71e312 ca78935 a162c90 c71e312 ca78935 c71e312 ca78935 c71e312 ca78935 3f2cfa1 ca78935 3f2cfa1 ca78935 3f2cfa1 14279a0 84b9e0c 0f7804c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | # src/expon/presentation/interfaces/rest/controllers/presentation_controller.py
from fastapi import APIRouter, UploadFile, File, Depends, HTTPException, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.expon.shared.infrastructure.dependencies import get_db
from src.expon.iam.infrastructure.authorization.sfs.auth_bearer import get_current_user
from src.expon.presentation.application.internal.commandservices.audio_upload_service import AudioUploadService
from src.expon.presentation.application.internal.queryservices.presentation_query_service import PresentationQueryService
from src.expon.presentation.infrastructure.persistence.jpa.repositories.presentation_repository import PresentationRepository
from src.expon.presentation.infrastructure.services.storage.local_storage_service import LocalStorageService
from src.expon.presentation.domain.services.transcription_service import TranscriptionService
from src.expon.presentation.domain.services.multimodal_service import MultimodalService # ← CAMBIO
from src.expon.presentation.interfaces.rest.responses.presentation_response import (
PresentationResponse,
AudioMetadataResponse,
PresentationSummaryResponse
)
from src.expon.feedback.infrastructure.persistence.jpa.feedback_repository import FeedbackRepository
from src.expon.feedback.interfaces.rest.feedback_response import FeedbackResponse
from src.expon.presentation.infrastructure.services.storage.supabase_storage_service import generate_signed_audio_url
router = APIRouter()
@router.post("/upload", response_model=PresentationResponse)
def upload_presentation(
file: UploadFile = File(...),
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
try:
contents = file.file.read()
if not contents:
raise HTTPException(status_code=400, detail="El archivo está vacío.")
file.file.seek(0)
repository = PresentationRepository(db)
storage_service = LocalStorageService()
transcription_service = TranscriptionService()
multimodal_service = MultimodalService() # ← CAMBIO
service = AudioUploadService(
storage_service=storage_service,
transcription_service=transcription_service,
multimodal_service=multimodal_service, # ← CAMBIO
repository=repository
)
presentation = service.upload_and_analyze(file, current_user.id)
return PresentationResponse(
id=presentation.id,
transcript=presentation.transcript,
dominant_emotion=presentation.dominant_emotion,
emotion_probabilities=presentation.emotion_probabilities,
confidence=presentation.confidence,
filename=presentation.filename,
metadata=AudioMetadataResponse(
duration=presentation.metadata.duration,
sample_rate=presentation.metadata.sample_rate,
language=presentation.metadata.language
),
created_at=presentation.created_at
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error al procesar el archivo: {str(e)}")
@router.get("/summary", response_model=list[PresentationSummaryResponse])
def get_presentations_summary(
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
repository = PresentationRepository(db)
query_service = PresentationQueryService(repository)
presentations = query_service.get_presentations_by_user(current_user.id)
return [
PresentationSummaryResponse(
id=p.id,
filename=p.filename,
dominant_emotion=p.dominant_emotion,
confidence=p.confidence,
created_at=p.created_at
) for p in presentations
]
@router.get("/{presentation_id}", response_model=PresentationResponse)
def get_presentation_by_id(
presentation_id: UUID,
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
repository = PresentationRepository(db)
query_service = PresentationQueryService(repository)
presentation = query_service.get_presentation_by_id_and_user(presentation_id, current_user.id)
if presentation is None:
raise HTTPException(status_code=404, detail="Presentación no encontrada")
return PresentationResponse(
id=presentation.id,
transcript=presentation.transcript,
dominant_emotion=presentation.dominant_emotion,
emotion_probabilities=presentation.emotion_probabilities,
confidence=presentation.confidence,
filename=presentation.filename,
metadata=AudioMetadataResponse(
duration=presentation.metadata.duration,
sample_rate=presentation.metadata.sample_rate,
language=presentation.metadata.language
),
created_at=presentation.created_at
)
@router.delete("/{presentation_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_presentation(
presentation_id: UUID,
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
repository = PresentationRepository(db)
presentation = repository.get_by_id_and_user(presentation_id, current_user.id)
if presentation is None:
raise HTTPException(status_code=404, detail="Presentación no encontrada")
# Eliminar archivo local
storage_service = LocalStorageService()
storage_service.delete(presentation.filename)
# Eliminar de base de datos
repository.delete(presentation)
@router.get("/feedback/presentation/{presentation_id}", response_model=FeedbackResponse)
def get_feedback_by_presentation(
presentation_id: UUID,
db: Session = Depends(get_db)
):
repo = FeedbackRepository(db)
feedback = repo.get_by_presentation(presentation_id)
if feedback is None:
raise HTTPException(status_code=404, detail="Feedback no encontrado")
return feedback
@router.get("/{presentation_id}/audio-url")
def get_audio_signed_url(
presentation_id: UUID,
db: Session = Depends(get_db),
current_user=Depends(get_current_user)
):
"""
Retorna una URL firmada temporal del audio asociado a la presentación.
"""
repository = PresentationRepository(db)
presentation = repository.get_by_id_and_user(presentation_id, current_user.id)
if presentation is None:
raise HTTPException(status_code=404, detail="Presentación no encontrada")
if not presentation.audio_path:
raise HTTPException(status_code=404, detail="No hay un audio asociado a esta presentación")
try:
signed_url = generate_signed_audio_url(presentation.audio_path)
return {"url": signed_url}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error generando URL firmada: {str(e)}") |