2025-07-27 14:26:30 +00:00
|
|
|
|
package utils
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-08-18 19:34:13 +00:00
|
|
|
|
"errors"
|
2025-07-27 14:26:30 +00:00
|
|
|
|
"fmt"
|
2025-08-18 19:34:13 +00:00
|
|
|
|
"log"
|
2025-07-27 14:26:30 +00:00
|
|
|
|
"os"
|
2025-08-18 19:34:13 +00:00
|
|
|
|
"path/filepath"
|
2025-08-18 19:41:40 +00:00
|
|
|
|
"strings"
|
2025-08-18 19:34:13 +00:00
|
|
|
|
|
2025-07-27 14:26:30 +00:00
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
|
2025-08-18 19:34:13 +00:00
|
|
|
|
"canguidev/shelfy/internal/models"
|
2025-07-27 14:26:30 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func CreateDefaultFolder(db *gorm.DB) {
|
2025-08-18 19:41:40 +00:00
|
|
|
|
// noms “logiques” attendus en base
|
|
|
|
|
|
targets := []string{"Film", "Série", "Manga", "Magazine"}
|
2025-07-27 14:26:30 +00:00
|
|
|
|
|
2025-08-18 19:41:40 +00:00
|
|
|
|
// 0) Nettoyage global : si des lignes ont path "upload/XXX", on les normalise en "XXX"
|
|
|
|
|
|
if err := normalizeExistingPaths(db); err != nil {
|
|
|
|
|
|
log.Printf("[DB] Warning: normalisation initiale partielle: %v", err)
|
|
|
|
|
|
}
|
2025-07-27 14:26:30 +00:00
|
|
|
|
|
2025-08-18 19:41:40 +00:00
|
|
|
|
for _, name := range targets {
|
|
|
|
|
|
diskPath := filepath.Join("upload", name) // répertoire physique
|
|
|
|
|
|
// 1) Toujours créer le dossier physique
|
|
|
|
|
|
if err := os.MkdirAll(diskPath, 0o755); err != nil {
|
|
|
|
|
|
log.Printf("[FOLDER] Erreur création '%s' : %v", diskPath, err)
|
2025-08-18 19:34:13 +00:00
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-18 19:41:40 +00:00
|
|
|
|
// 2) En base : on veut UNE ligne unique avec Path=Name et PathName=Name
|
|
|
|
|
|
// On cherche tout ce qui pourrait correspondre à ce nom (avec ou sans "upload/")
|
|
|
|
|
|
var rows []models.PathDownload
|
|
|
|
|
|
if err := db.Where("path = ? OR path = ? OR path_name = ? OR path_name = ?",
|
|
|
|
|
|
name, "upload/"+name, name, "upload/"+name,
|
|
|
|
|
|
).Find(&rows).Error; err != nil {
|
|
|
|
|
|
log.Printf("[DB] Lookup '%s' échouée : %v", name, err)
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2025-08-18 19:34:13 +00:00
|
|
|
|
|
2025-08-18 19:41:40 +00:00
|
|
|
|
switch len(rows) {
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
// 2a) Rien trouvé → créer la ligne normalisée
|
|
|
|
|
|
row := models.PathDownload{Path: name, PathName: name}
|
2025-08-18 19:34:13 +00:00
|
|
|
|
if err := db.Create(&row).Error; err != nil {
|
2025-08-18 19:41:40 +00:00
|
|
|
|
log.Printf("[DB] Création PathDownload('%s') KO : %v", name, err)
|
2025-07-27 14:26:30 +00:00
|
|
|
|
} else {
|
2025-08-18 19:41:40 +00:00
|
|
|
|
log.Printf("[DB] Créé PathDownload id=%v (%s)", row.ID, name)
|
2025-08-18 19:34:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
2025-08-18 19:41:40 +00:00
|
|
|
|
// 2b) On a des lignes → on les normalise et on garde une seule
|
|
|
|
|
|
// 1) mettre à jour la première ligne en Path=Name, PathName=Name
|
|
|
|
|
|
main := rows[0]
|
|
|
|
|
|
needUpdate := (main.Path != name) || (main.PathName != name)
|
|
|
|
|
|
if needUpdate {
|
|
|
|
|
|
if err := db.Model(&main).Updates(map[string]any{
|
|
|
|
|
|
"path": name,
|
|
|
|
|
|
"path_name": name,
|
|
|
|
|
|
}).Error; err != nil {
|
|
|
|
|
|
log.Printf("[DB] Update id=%v -> (%s|%s) KO : %v", main.ID, name, name, err)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
log.Printf("[DB] Normalisé id=%v -> (%s|%s)", main.ID, name, name)
|
|
|
|
|
|
}
|
2025-08-18 19:34:13 +00:00
|
|
|
|
}
|
2025-08-18 19:41:40 +00:00
|
|
|
|
|
|
|
|
|
|
// 2) supprimer les doublons résiduels (même nom logique)
|
|
|
|
|
|
if len(rows) > 1 {
|
|
|
|
|
|
var dupIDs []uint
|
|
|
|
|
|
for _, r := range rows[1:] {
|
|
|
|
|
|
dupIDs = append(dupIDs, r.ID)
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := db.Where("id IN ?", dupIDs).Delete(&models.PathDownload{}).Error; err != nil {
|
|
|
|
|
|
log.Printf("[DB] Suppression doublons (%v) KO : %v", dupIDs, err)
|
2025-08-18 19:34:13 +00:00
|
|
|
|
} else {
|
2025-08-18 19:41:40 +00:00
|
|
|
|
log.Printf("[DB] Doublons supprimés pour '%s' : %v", name, dupIDs)
|
2025-07-27 14:26:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-18 19:34:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-18 19:41:40 +00:00
|
|
|
|
log.Printf("[FOLDER] OK : %s (DB='%s')", diskPath, name)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// normalizeExistingPaths met à jour toutes les lignes dont path commence par "upload/"
|
|
|
|
|
|
// en supprimant ce préfixe, et aligne path_name si nécessaire. Elle supprime aussi
|
|
|
|
|
|
// d’éventuels doublons créés par cette normalisation.
|
|
|
|
|
|
func normalizeExistingPaths(db *gorm.DB) error {
|
|
|
|
|
|
// 1) Récupérer les lignes impactées
|
|
|
|
|
|
var rows []models.PathDownload
|
|
|
|
|
|
if err := db.Where("path LIKE ?", "upload/%").Find(&rows).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, r := range rows {
|
|
|
|
|
|
trimmed := strings.TrimPrefix(r.Path, "upload/")
|
|
|
|
|
|
updates := map[string]any{"path": trimmed}
|
|
|
|
|
|
if r.PathName == "" || strings.HasPrefix(r.PathName, "upload/") {
|
|
|
|
|
|
updates["path_name"] = trimmed
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := db.Model(&r).Updates(updates).Error; err != nil {
|
|
|
|
|
|
return fmt.Errorf("update id=%v (%s -> %s) : %w", r.ID, r.Path, trimmed, err)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2) Éliminer d’éventuels doublons (même path normalisé), on garde le plus petit id
|
|
|
|
|
|
type rec struct {
|
|
|
|
|
|
ID uint
|
|
|
|
|
|
Path string
|
|
|
|
|
|
}
|
|
|
|
|
|
var all []rec
|
|
|
|
|
|
if err := db.Model(&models.PathDownload{}).Select("id, path").Order("path, id").Scan(&all).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
seen := make(map[string]uint)
|
|
|
|
|
|
var dupIDs []uint
|
|
|
|
|
|
for _, r := range all {
|
|
|
|
|
|
if keep, ok := seen[r.Path]; ok {
|
|
|
|
|
|
// doublon : on marque pour suppression
|
|
|
|
|
|
dupIDs = append(dupIDs, r.ID)
|
|
|
|
|
|
_ = keep
|
|
|
|
|
|
} else {
|
|
|
|
|
|
seen[r.Path] = r.ID
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(dupIDs) > 0 {
|
|
|
|
|
|
if err := db.Where("id IN ?", dupIDs).Delete(&models.PathDownload{}).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
|
|
|
|
return fmt.Errorf("delete dups %v : %w", dupIDs, err)
|
2025-07-27 14:26:30 +00:00
|
|
|
|
}
|
2025-08-18 19:41:40 +00:00
|
|
|
|
log.Printf("[DB] Doublons supprimés après normalisation: %v", dupIDs)
|
2025-07-27 14:26:30 +00:00
|
|
|
|
}
|
2025-08-18 19:41:40 +00:00
|
|
|
|
return nil
|
2025-08-18 19:34:13 +00:00
|
|
|
|
}
|