File size: 3,087 Bytes
ce07694
 
 
 
8a5f1ff
ce07694
1d9bafe
 
ce07694
09c6574
 
ce07694
8a5f1ff
 
ce07694
 
 
 
09c6574
ce07694
 
09c6574
 
 
 
 
ce07694
 
 
8a5f1ff
ce07694
09c6574
 
8a5f1ff
09c6574
 
 
 
 
 
8a5f1ff
09c6574
 
 
 
 
8a5f1ff
 
84fa173
09c6574
 
84fa173
8a5f1ff
ce07694
 
 
1d9bafe
ce07694
8a5f1ff
ce07694
 
 
 
1d9bafe
ce07694
8a5f1ff
 
ce07694
 
1d9bafe
ce07694
1d9bafe
8a5f1ff
 
1d9bafe
 
 
 
 
 
 
 
 
 
8a5f1ff
 
1d9bafe
 
 
 
 
8a5f1ff
 
1d9bafe
 
84fa173
8a5f1ff
ce07694
8a5f1ff
 
ce07694
 
 
8a5f1ff
 
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
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)
}