anput-api / handler /http.go
alberdjuniawan's picture
refactor: standardize API response
8a5f1ff
Raw History Blame Contribute Delete
3.09 kB
package handler
import (
"io"
"log"
"net/http"
"os"
"os/exec"
"github.com/alberdjuniawan/anput-api/middleware"
"github.com/alberdjuniawan/anput-api/repository"
"github.com/alberdjuniawan/anput-api/service"
"github.com/alberdjuniawan/anput-api/util"
chiMiddleware "github.com/go-chi/chi/v5/middleware"
)
type HTTPHandler struct {
AIService service.AIService
Repo repository.Repository
}
func NewHTTPHandler(aiService service.AIService, repo repository.Repository) *HTTPHandler {
return &HTTPHandler{
AIService: aiService,
Repo: repo,
}
}
func (h *HTTPHandler) UploadAudioFile(w http.ResponseWriter, r *http.Request) {
reqID := chiMiddleware.GetReqID(r.Context())
userIDVal := r.Context().Value(middleware.UserIDKey)
if userIDVal == nil {
util.WriteError(w, http.StatusUnauthorized, "Unauthorized access", reqID)
return
}
userID := userIDVal.(string)
slug := r.URL.Query().Get("slug")
if slug == "" {
util.WriteError(w, http.StatusBadRequest, "Missing query parameter: slug", reqID)
return
}
schemaData, err := h.Repo.GetSchemaBySlug(r.Context(), userID, slug)
if err != nil {
log.Printf("[%s] Schema lookup error: %v", reqID, err)
util.WriteError(w, http.StatusNotFound, "Schema not found", reqID)
return
}
if err := r.ParseMultipartForm(50 << 20); err != nil {
util.WriteError(w, http.StatusBadRequest, "File too big (Max 50MB)", reqID)
return
}
file, header, err := r.FormFile("audio")
if err != nil {
util.WriteError(w, http.StatusBadRequest, "Missing audio file field", reqID)
return
}
defer file.Close()
tempInput, err := os.CreateTemp("", "raw-upload-*"+header.Filename)
if err != nil {
log.Printf("[%s] Temp file creation error: %v", reqID, err)
util.WriteError(w, http.StatusInternalServerError, "Internal storage error", reqID)
return
}
defer os.Remove(tempInput.Name())
if _, err := io.Copy(tempInput, file); err != nil {
log.Printf("[%s] File write error: %v", reqID, err)
util.WriteError(w, http.StatusInternalServerError, "Failed to save audio", reqID)
return
}
tempInput.Close()
tempOutput := tempInput.Name() + ".wav"
defer os.Remove(tempOutput)
cmd := exec.Command("ffmpeg", "-y", "-i", tempInput.Name(), "-ar", "16000", "-ac", "1", "-c:a", "pcm_s16le", tempOutput)
if output, err := cmd.CombinedOutput(); err != nil {
log.Printf("[%s] FFmpeg Error: %v | Output: %s", reqID, err, string(output))
util.WriteError(w, http.StatusBadRequest, "Audio conversion failed. Please verify your audio format.", reqID)
return
}
cleanAudioBytes, err := os.ReadFile(tempOutput)
if err != nil {
log.Printf("[%s] Read converted file error: %v", reqID, err)
util.WriteError(w, http.StatusInternalServerError, "Processing error", reqID)
return
}
result, err := h.AIService.ProcessAudioFull(r.Context(), cleanAudioBytes, schemaData.Definition)
if err != nil {
log.Printf("[%s] AI Processing Error: %v", reqID, err)
util.WriteError(w, http.StatusInternalServerError, "AI processing failed", reqID)
return
}
util.WriteSuccess(w, http.StatusOK, result, reqID)
}