package handlers import ( "net/http" "github.com/google/uuid" // "strconv" // Removed this import apperrors "veza-backend-api/internal/errors" "veza-backend-api/internal/services" "github.com/gin-gonic/gin" ) // HLSHandler gère les requêtes pour servir les fichiers HLS type HLSHandler struct { hlsService *services.HLSService } // NewHLSHandler crée un nouveau handler HLS func NewHLSHandler(hlsService *services.HLSService) *HLSHandler { return &HLSHandler{hlsService: hlsService} } // ServeMasterPlaylist sert le master playlist pour un track func (h *HLSHandler) ServeMasterPlaylist(c *gin.Context) { trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"}) return } playlist, err := h.hlsService.GetMasterPlaylist(c.Request.Context(), trackID) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"}) return } c.Header("Content-Type", "application/vnd.apple.mpegurl") c.Header("Cache-Control", "no-cache") c.String(http.StatusOK, playlist) } // ServeQualityPlaylist sert une quality playlist pour un track et bitrate func (h *HLSHandler) ServeQualityPlaylist(c *gin.Context) { trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"}) return } bitrate := c.Param("bitrate") playlist, err := h.hlsService.GetQualityPlaylist(c.Request.Context(), trackID, bitrate) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"}) return } c.Header("Content-Type", "application/vnd.apple.mpegurl") c.Header("Cache-Control", "no-cache") c.String(http.StatusOK, playlist) } // ServeSegment sert un segment pour un track, bitrate et nom de segment func (h *HLSHandler) ServeSegment(c *gin.Context) { trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"}) return } bitrate := c.Param("bitrate") segment := c.Param("segment") segmentPath, err := h.hlsService.GetSegmentPath(c.Request.Context(), trackID, bitrate, segment) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "segment not found"}) return } c.Header("Content-Type", "video/mp2t") c.Header("Cache-Control", "public, max-age=3600") c.File(segmentPath) } // GetStreamInfo retourne les informations générales d'un stream HLS pour un track // GET /api/v1/tracks/:id/hls/info // BE-API-020: Implement HLS stream info endpoint func (h *HLSHandler) GetStreamInfo(c *gin.Context) { trackID, err := uuid.Parse(c.Param("id")) if err != nil { RespondWithAppError(c, apperrors.NewValidationError("invalid track id")) return } info, err := h.hlsService.GetStreamInfo(c.Request.Context(), trackID) if err != nil { if err.Error()[:20] == "HLS stream not found" { RespondWithAppError(c, apperrors.NewNotFoundError("HLS stream")) return } RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to get stream info", err)) return } RespondSuccess(c, http.StatusOK, info) } // GetStreamStatus retourne le statut d'un stream HLS pour un track // GET /api/v1/tracks/:id/hls/status // BE-API-020: Implement HLS stream info endpoint func (h *HLSHandler) GetStreamStatus(c *gin.Context) { trackID, err := uuid.Parse(c.Param("id")) if err != nil { RespondWithAppError(c, apperrors.NewValidationError("invalid track id")) return } status, err := h.hlsService.GetStreamStatus(c.Request.Context(), trackID) if err != nil { if err.Error()[:20] == "HLS stream not found" { RespondWithAppError(c, apperrors.NewNotFoundError("HLS stream")) return } RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to get stream status", err)) return } RespondSuccess(c, http.StatusOK, status) } // TriggerTranscode déclenche le transcodage HLS d'un track via la queue (T0343) func (h *HLSHandler) TriggerTranscode(c *gin.Context) { userID, ok := GetUserIDUUID(c) if !ok { return // Erreur déjà envoyée par GetUserIDUUID } if userID == uuid.Nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"}) return } jobID, err := h.hlsService.TriggerTranscodeQueue(c.Request.Context(), trackID, userID) if err != nil { if err.Error() == "track not found" { c.JSON(http.StatusNotFound, gin.H{"error": "track not found"}) return } if err.Error() == "forbidden: user does not own this track" { c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusAccepted, gin.H{"job_id": jobID}) }