This commit is contained in:
+34
-3
@@ -147,6 +147,7 @@ func RegisterRoutes(router *gin.Engine, app *App) {
|
||||
router.POST("/api/download/preview", app.previewDownload)
|
||||
router.POST("/api/upload", app.uploadFile)
|
||||
router.POST("/api/download", app.startDownload)
|
||||
router.POST("/api/translate/summary", app.translateSummary)
|
||||
router.POST("/api/search", app.searchMedia)
|
||||
}
|
||||
|
||||
@@ -343,6 +344,28 @@ func (a *App) previewDownload(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, preview)
|
||||
}
|
||||
|
||||
func (a *App) translateSummary(c *gin.Context) {
|
||||
var req struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
req.Text = strings.TrimSpace(req.Text)
|
||||
if req.Text == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "text is required"})
|
||||
return
|
||||
}
|
||||
|
||||
translated, err := a.GeminiService.TranslateSummaryToKorean(req.Text)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"translatedText": translated})
|
||||
}
|
||||
|
||||
func (a *App) runDownload(recordID int64, url, start, end, quality, outputPath string) {
|
||||
a.Hub.Broadcast("progress", gin.H{"type": "download", "status": "queued", "progress": 0, "url": url})
|
||||
a.debug("download command started", gin.H{"url": url, "start": start, "end": end, "quality": quality, "outputPath": outputPath})
|
||||
@@ -416,7 +439,7 @@ func (a *App) searchMedia(c *gin.Context) {
|
||||
|
||||
enabledPlatforms := normalizePlatforms(req.Platforms)
|
||||
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "searching " + selectedPlatformLabel(enabledPlatforms), "progress": 35})
|
||||
results, err := a.SearchService.SearchMediaWithDeadline(queryVariants, enabledPlatforms, deadline.Add(-20*time.Second))
|
||||
results, searchMeta, err := a.SearchService.SearchMediaWithDeadline(queryVariants, enabledPlatforms, deadline.Add(-20*time.Second))
|
||||
if err != nil {
|
||||
a.debug("search backend failed", gin.H{"error": err.Error(), "variants": queryVariants, "durationMs": time.Since(started).Milliseconds()})
|
||||
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "search failed", "progress": 100, "message": err.Error()})
|
||||
@@ -441,10 +464,12 @@ func (a *App) searchMedia(c *gin.Context) {
|
||||
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "analyzing all candidate visuals with Gemini Vision", "progress": 75})
|
||||
recommended, geminiStats, geminiErr := services.EvaluateAllCandidatesWithGeminiWithDeadline(a.GeminiService, req.Query, scored, deadline.Add(-5*time.Second))
|
||||
a.debug("search gemini evaluation", geminiStats)
|
||||
supplementalDeadlineLimited := false
|
||||
if services.NeedsSupplementalExploration(recommended) && time.Now().Before(deadline.Add(-10*time.Second)) {
|
||||
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "Gemini 평가가 약해 추가 후보를 탐색하는 중", "progress": 82})
|
||||
explorationQueries := buildSupplementalQueries(req.Query, queryVariants)
|
||||
extraResults, extraErr := a.SearchService.SearchMediaWithDeadline(explorationQueries, enabledPlatforms, deadline.Add(-10*time.Second))
|
||||
extraResults, extraMeta, extraErr := a.SearchService.SearchMediaWithDeadline(explorationQueries, enabledPlatforms, deadline.Add(-10*time.Second))
|
||||
supplementalDeadlineLimited = extraMeta.PartialDueToDeadline
|
||||
if extraErr == nil && len(extraResults) > 0 {
|
||||
results = mergeSearchResults(results, extraResults)
|
||||
scored = services.RankSearchResults(strings.Join(explorationQueries[:min(len(explorationQueries), 3)], " "), results)
|
||||
@@ -468,6 +493,8 @@ func (a *App) searchMedia(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if services.NeedsSupplementalExploration(recommended) {
|
||||
supplementalDeadlineLimited = true
|
||||
}
|
||||
if geminiErr != nil && len(recommended) == 0 {
|
||||
warning := geminiErr.Error()
|
||||
@@ -503,13 +530,17 @@ func (a *App) searchMedia(c *gin.Context) {
|
||||
if warning != "" {
|
||||
response["warning"] = warning
|
||||
}
|
||||
if time.Now().After(deadline.Add(-2*time.Second)) && warning == "" {
|
||||
if shouldWarnPartialSearch(searchMeta, geminiStats, supplementalDeadlineLimited, warning) {
|
||||
response["warning"] = "search returned partial results to avoid gateway timeout"
|
||||
}
|
||||
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "search complete", "progress": 100})
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
func shouldWarnPartialSearch(meta services.SearchExecutionMeta, stats services.GeminiBatchStats, supplementalDeadlineLimited bool, warning string) bool {
|
||||
return warning == "" && (meta.PartialDueToDeadline || stats.DeadlineLimited || supplementalDeadlineLimited)
|
||||
}
|
||||
|
||||
func normalizeFilename(name string) string {
|
||||
base := strings.ToLower(strings.TrimSpace(name))
|
||||
ext := filepath.Ext(base)
|
||||
|
||||
Reference in New Issue
Block a user