diff --git a/internal/download/jobs.go b/internal/download/jobs.go index b1e1db6..fe89396 100644 --- a/internal/download/jobs.go +++ b/internal/download/jobs.go @@ -254,7 +254,7 @@ func StartDownload(job *DownloadJob, downloadURL string, client *debridlink.Clie close(done) // Fusion - safeName := sanitizeFileName(job.Name) + safeName := SanitizeFileName(job.Name) finalPath := generateUniqueFilePath(path.Path, safeName) out, err := os.Create(finalPath) @@ -325,7 +325,7 @@ func StartDownloadSingleThread(job *DownloadJob, downloadURL string, db *gorm.DB return } - destPath := filepath.Join(basePath, sanitizeFileName(job.Name)) + destPath := filepath.Join(basePath, SanitizeFileName(job.Name)) outFile, err := os.Create(destPath) if err != nil { log.Printf("[ERROR] Impossible de créer le fichier : %v\n", err) @@ -412,7 +412,7 @@ func downloadSegment(url string, start, end int64, dest string, progressChan cha return nil } -func sanitizeFileName(name string) string { +func SanitizeFileName(name string) string { re := regexp.MustCompile(`[^\w\-.]`) return re.ReplaceAllString(name, "_") } diff --git a/internal/route/main.go b/internal/route/main.go index a917c44..653e117 100644 --- a/internal/route/main.go +++ b/internal/route/main.go @@ -216,7 +216,7 @@ func RoutesProtected(r *mux.Router, bd *gorm.DB) { r.HandleFunc("/api/pathDownload/update/{id}", download.UpdateSavePath(bd)).Methods("PUT") r.HandleFunc("/api/pathDownload/delete/{id}", download.DeleteSavePath(bd)).Methods("DELETE") r.HandleFunc("/api/pathDownload/all/", download.ReadAllSavePath(bd)).Methods("GET") - + r.HandleFunc("/api/download/add-multiple", renders.HandleAddJobsMultiple(bd)).Methods("POST") //API Check path r.HandleFunc("/validate-path", download.PathValidationHandler) diff --git a/renders/renders.go b/renders/renders.go index ff093b7..d3f87c1 100644 --- a/renders/renders.go +++ b/renders/renders.go @@ -704,6 +704,104 @@ func DetailHandler(w http.ResponseWriter, r *http.Request) { }) } +func HandleAddJobsMultiple(db *gorm.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + http.Error(w, "Requête invalide", http.StatusBadRequest) + return + } + + // Récupération des liens + raw := r.FormValue("links") + lines := strings.Split(raw, "\n") + + // Chemin de base + pathIDStr := r.FormValue("path_id") + id, err := strconv.Atoi(pathIDStr) + if err != nil { + http.Error(w, "ID de chemin invalide", http.StatusBadRequest) + return + } + var basePath models.PathDownload + if err := db.First(&basePath, id).Error; err != nil { + http.Error(w, "Chemin introuvable", http.StatusBadRequest) + return + } + + // Création d'un sous-dossier si renseigné + sub := strings.TrimSpace(r.FormValue("new_subfolder")) + finalDir := basePath.Path + if sub != "" { + finalDir = filepath.Join(basePath.Path, sanitizeFileName(sub)) + if err := os.MkdirAll(finalDir, os.ModePerm); err != nil { + log.Printf("Erreur création dossier: %v", err) + http.Error(w, "Impossible de créer le sous-dossier", http.StatusInternalServerError) + return + } + } + + client := debridlink.NewClient(db) + account := download.GetFirstActiveAccount(client) + if account == nil { + http.Error(w, "Aucun compte Debrid-Link actif", http.StatusBadRequest) + return + } + client.SetAccount(account) + + for _, link := range lines { + link = strings.TrimSpace(link) + if link == "" { + continue + } + // Débride chaque lien + links, err := client.AddLink(context.Background(), link) + if err != nil { + log.Printf("Echec débridage pour %s: %v", link, err) + continue + } + + for _, l := range links { + // Création transcode si nécessaire + streamInfo, err := client.CreateTranscode(context.Background(), l.ID) + if err != nil { + log.Println("Erreur transcode:", err) + } + + job := &download.DownloadJob{ + ID: l.ID, + Link: l.DownloadURL, + Name: l.Name, + Status: "waiting", + PathID: id, + Size: l.Size, + Host: l.Host, + Progress: 0, + StreamURL: streamInfo.StreamURL, + } + if err := download.RegisterJobWithDB(job, db); err != nil { + log.Printf("Erreur enregistrement job: %v", err) + } + } + } + + // Mise à jour vue + data := map[string]interface{}{ + "jobs": download.ListJobs(db), + "paths": getAllPaths(db), + } + download.Broadcast() + renderPartial(w, "downloads_table", data) + } +} +func getAllPaths(db *gorm.DB) []*models.PathDownload { + var paths []*models.PathDownload + db.Order("name").Find(&paths) + return paths +} +func sanitizeFileName(name string) string { + // même regex que download.sanitizeFileName + return download.SanitizeFileName(name) +} diff --git a/templates/godownloader_download.pages.tmpl b/templates/godownloader_download.pages.tmpl index 0825f79..5a3a60d 100644 --- a/templates/godownloader_download.pages.tmpl +++ b/templates/godownloader_download.pages.tmpl @@ -1,36 +1,31 @@