feat: add modpack versions API endpoint

This commit is contained in:
2026-01-06 19:09:15 +03:00
parent 9e2657c709
commit 1cdfe9fefc
4 changed files with 113 additions and 17 deletions

View File

@@ -7,7 +7,9 @@ import (
"io"
"log/slog"
"net/http"
"net/url"
"os"
"path"
"gitea.mrixs.me/minecraft-platform/backend/internal/core"
"gitea.mrixs.me/minecraft-platform/backend/internal/core/importer"
@@ -203,3 +205,80 @@ func (h *ModpackHandler) updateJobStatus(ctx context.Context, jobID int, status
msg, _ := json.Marshal(update)
h.Hub.BroadcastMessage(msg)
}
// ModpackVersionResponse представляет версию модпака для ответа API
type ModpackVersionResponse struct {
FileID int `json:"file_id"`
DisplayName string `json:"display_name"`
FileName string `json:"file_name"`
FileDate string `json:"file_date"`
GameVersions []string `json:"game_versions"`
}
// GetModpackVersions возвращает список доступных версий для модпака по URL
func (h *ModpackHandler) GetModpackVersions(w http.ResponseWriter, r *http.Request) {
pageURL := r.URL.Query().Get("url")
if pageURL == "" {
http.Error(w, "Missing 'url' query parameter", http.StatusBadRequest)
return
}
apiKey := os.Getenv("CURSEFORGE_API_KEY")
if apiKey == "" {
http.Error(w, "CurseForge API key not configured", http.StatusInternalServerError)
return
}
cfImporter := importer.NewCurseForgeImporter("", apiKey)
// Извлекаем slug из URL
parsedURL, err := parseModpackURL(pageURL)
if err != nil {
http.Error(w, fmt.Sprintf("Invalid URL: %v", err), http.StatusBadRequest)
return
}
// Ищем проект по slug
projectID, err := cfImporter.FindModpackBySlug(parsedURL)
if err != nil {
http.Error(w, fmt.Sprintf("Modpack not found: %v", err), http.StatusNotFound)
return
}
// Получаем список файлов (версий)
files, err := cfImporter.GetModpackFiles(projectID)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to get versions: %v", err), http.StatusInternalServerError)
return
}
// Преобразуем в ответ
var versions []ModpackVersionResponse
for _, f := range files {
versions = append(versions, ModpackVersionResponse{
FileID: f.ID,
DisplayName: f.DisplayName,
FileName: f.FileName,
FileDate: f.FileDate,
GameVersions: f.GameVersions,
})
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(versions)
}
// parseModpackURL извлекает slug из URL страницы CurseForge
func parseModpackURL(rawURL string) (string, error) {
parsed, err := url.Parse(rawURL)
if err != nil {
return "", err
}
// URL вида https://www.curseforge.com/minecraft/modpacks/all-the-mods-9
// path.Base вернет "all-the-mods-9"
slug := path.Base(parsed.Path)
if slug == "" || slug == "." || slug == "/" {
return "", fmt.Errorf("could not extract modpack slug from URL")
}
return slug, nil
}