Files
backend/internal/database/modpack_repository.go

129 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package database
import (
"context"
"gitea.mrixs.me/minecraft-platform/backend/internal/models"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
type ModpackRepository struct {
DB *pgxpool.Pool
}
// CreateModpackTx создает модпак и все его файлы в одной транзакции.
func (r *ModpackRepository) CreateModpackTx(ctx context.Context, modpack *models.Modpack, files []models.ModpackFile) error {
tx, err := r.DB.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
var modpackID int
err = tx.QueryRow(ctx,
"INSERT INTO modpacks (name, display_name, minecraft_version) VALUES ($1, $2, $3) RETURNING id",
modpack.Name, modpack.DisplayName, modpack.MinecraftVersion,
).Scan(&modpackID)
if err != nil {
return err
}
rows := make([][]interface{}, len(files))
for i, f := range files {
rows[i] = []interface{}{modpackID, f.RelativePath, f.FileHash, f.FileSize, f.DownloadURL}
}
_, err = tx.CopyFrom(
ctx,
pgx.Identifier{"modpack_files"},
[]string{"modpack_id", "relative_path", "file_hash", "file_size", "download_url"},
pgx.CopyFromRows(rows),
)
if err != nil {
return err
}
return tx.Commit(ctx)
}
// GetModpackManifest возвращает список файлов для указанного модпака.
func (r *ModpackRepository) GetModpackManifest(ctx context.Context, modpackName string) ([]models.ManifestEntry, error) {
query := `
SELECT mf.relative_path, mf.file_hash, mf.file_size
FROM modpack_files mf
JOIN modpacks m ON mf.modpack_id = m.id
WHERE m.name = $1 AND m.is_active = TRUE`
rows, err := r.DB.Query(ctx, query, modpackName)
if err != nil {
return nil, err
}
defer rows.Close()
var manifest []models.ManifestEntry
for rows.Next() {
var entry models.ManifestEntry
if err := rows.Scan(&entry.Path, &entry.Hash, &entry.Size); err != nil {
return nil, err
}
manifest = append(manifest, entry)
}
if len(manifest) == 0 {
var exists bool
err := r.DB.QueryRow(ctx, "SELECT EXISTS(SELECT 1 FROM modpacks WHERE name = $1)", modpackName).Scan(&exists)
if err != nil || !exists {
return nil, pgx.ErrNoRows
}
}
return manifest, nil
}
// GetAllFileHashes извлекает все уникальные хеши файлов из базы данных.
func (r *ModpackRepository) GetAllFileHashes(ctx context.Context) (map[string]struct{}, error) {
query := "SELECT DISTINCT file_hash FROM modpack_files"
rows, err := r.DB.Query(ctx, query)
if err != nil {
return nil, err
}
defer rows.Close()
hashes := make(map[string]struct{})
for rows.Next() {
var hash string
if err := rows.Scan(&hash); err != nil {
return nil, err
}
hashes[hash] = struct{}{}
}
return hashes, rows.Err()
}
// GetModpacksSummary возвращает список всех активных модпаков с датой последнего обновления.
func (r *ModpackRepository) GetModpacksSummary(ctx context.Context) ([]models.ModpackSummary, error) {
query := `
SELECT name, updated_at
FROM modpacks
WHERE is_active = TRUE`
rows, err := r.DB.Query(ctx, query)
if err != nil {
return nil, err
}
defer rows.Close()
var summaries []models.ModpackSummary
for rows.Next() {
var s models.ModpackSummary
if err := rows.Scan(&s.Name, &s.UpdatedAt); err != nil {
return nil, err
}
summaries = append(summaries, s)
}
return summaries, nil
}