mirror of
https://github.com/Direct-Dev-Ru/go-lcg.git
synced 2025-11-16 01:29:55 +00:00
206 lines
6.1 KiB
Go
206 lines
6.1 KiB
Go
package serve
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/direct-dev-ru/linux-command-gpt/config"
|
|
)
|
|
|
|
// SaveResultRequest представляет запрос на сохранение результата
|
|
type SaveResultRequest struct {
|
|
Prompt string `json:"prompt"`
|
|
Command string `json:"command"`
|
|
Explanation string `json:"explanation,omitempty"`
|
|
Model string `json:"model"`
|
|
}
|
|
|
|
// SaveResultResponse представляет ответ на сохранение результата
|
|
type SaveResultResponse struct {
|
|
Success bool `json:"success"`
|
|
Message string `json:"message"`
|
|
File string `json:"file,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// AddToHistoryRequest представляет запрос на добавление в историю
|
|
type AddToHistoryRequest struct {
|
|
Prompt string `json:"prompt"`
|
|
Command string `json:"command"`
|
|
Response string `json:"response"`
|
|
Explanation string `json:"explanation,omitempty"`
|
|
System string `json:"system"`
|
|
}
|
|
|
|
// AddToHistoryResponse представляет ответ на добавление в историю
|
|
type AddToHistoryResponse struct {
|
|
Success bool `json:"success"`
|
|
Message string `json:"message"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// handleSaveResult обрабатывает сохранение результата
|
|
func handleSaveResult(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req SaveResultRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.Prompt == "" || req.Command == "" {
|
|
http.Error(w, "Prompt and command are required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Создаем папку результатов если не существует
|
|
if err := os.MkdirAll(config.AppConfig.ResultFolder, 0755); err != nil {
|
|
apiJsonResponse(w, SaveResultResponse{
|
|
Success: false,
|
|
Error: "Failed to create result folder",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Генерируем имя файла
|
|
timestamp := time.Now().Format("2006-01-02_15-04-05")
|
|
filename := fmt.Sprintf("gpt_request_%s_%s.md", req.Model, timestamp)
|
|
filePath := path.Join(config.AppConfig.ResultFolder, filename)
|
|
title := truncateTitle(req.Prompt)
|
|
|
|
// Формируем содержимое
|
|
var content string
|
|
if strings.TrimSpace(req.Explanation) != "" {
|
|
content = fmt.Sprintf("# %s\n\n## Prompt\n\n%s\n\n## Response\n\n%s\n\n## Explanation\n\n%s\n",
|
|
title, req.Prompt, req.Command, req.Explanation)
|
|
} else {
|
|
content = fmt.Sprintf("# %s\n\n## Prompt\n\n%s\n\n## Response\n\n%s\n",
|
|
title, req.Prompt, req.Command)
|
|
}
|
|
|
|
// Сохраняем файл
|
|
if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
|
|
apiJsonResponse(w, SaveResultResponse{
|
|
Success: false,
|
|
Error: "Failed to save file",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Debug вывод для сохранения результата
|
|
PrintWebSaveDebugInfo("SAVE_RESULT", req.Prompt, req.Command, req.Explanation, req.Model, filename)
|
|
|
|
apiJsonResponse(w, SaveResultResponse{
|
|
Success: true,
|
|
Message: "Result saved successfully",
|
|
File: filename,
|
|
})
|
|
}
|
|
|
|
// handleAddToHistory обрабатывает добавление в историю
|
|
func handleAddToHistory(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req AddToHistoryRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.Prompt == "" || req.Command == "" || req.Response == "" {
|
|
http.Error(w, "Prompt, command and response are required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Проверяем, есть ли уже такой запрос в истории
|
|
entries, err := Read(config.AppConfig.ResultHistory)
|
|
if err != nil {
|
|
// Если файл не существует, создаем пустой массив
|
|
entries = []HistoryEntry{}
|
|
}
|
|
|
|
// Ищем дубликат
|
|
duplicateIndex := -1
|
|
for i, entry := range entries {
|
|
if strings.EqualFold(strings.TrimSpace(entry.Command), strings.TrimSpace(req.Prompt)) {
|
|
duplicateIndex = i
|
|
break
|
|
}
|
|
}
|
|
|
|
// Создаем новую запись
|
|
newEntry := HistoryEntry{
|
|
Index: len(entries) + 1,
|
|
Command: req.Prompt,
|
|
Response: req.Response,
|
|
Explanation: req.Explanation,
|
|
System: req.System,
|
|
Timestamp: time.Now(),
|
|
}
|
|
|
|
if duplicateIndex == -1 {
|
|
// Добавляем новую запись
|
|
entries = append(entries, newEntry)
|
|
} else {
|
|
// Перезаписываем существующую
|
|
newEntry.Index = entries[duplicateIndex].Index
|
|
entries[duplicateIndex] = newEntry
|
|
}
|
|
|
|
// Сохраняем историю
|
|
if err := Write(config.AppConfig.ResultHistory, entries); err != nil {
|
|
apiJsonResponse(w, AddToHistoryResponse{
|
|
Success: false,
|
|
Error: "Failed to save to history",
|
|
})
|
|
return
|
|
}
|
|
|
|
message := "Added to history successfully"
|
|
if duplicateIndex != -1 {
|
|
message = "Updated existing history entry"
|
|
}
|
|
|
|
// Debug вывод для добавления в историю
|
|
PrintWebSaveDebugInfo("ADD_TO_HISTORY", req.Prompt, req.Command, req.Explanation, req.System, "")
|
|
|
|
apiJsonResponse(w, AddToHistoryResponse{
|
|
Success: true,
|
|
Message: message,
|
|
})
|
|
}
|
|
|
|
// apiJsonResponse отправляет JSON ответ
|
|
func apiJsonResponse(w http.ResponseWriter, data interface{}) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(data); err != nil {
|
|
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
// truncateTitle сокращает строку до 120 символов (по рунам), добавляя " ..." при усечении
|
|
func truncateTitle(s string) string {
|
|
const maxLen = 120
|
|
if runeCount := len([]rune(s)); runeCount <= maxLen {
|
|
return s
|
|
}
|
|
const head = 116
|
|
r := []rune(s)
|
|
if len(r) <= head {
|
|
return s
|
|
}
|
|
return string(r[:head]) + " ..."
|
|
}
|