This commit is contained in:
cangui 2025-06-20 20:17:24 +02:00
parent 5d1377dddb
commit ebb2db9e39
4 changed files with 125 additions and 32 deletions

View File

@ -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, "_")
}

View File

@ -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)

View File

@ -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)
}

View File

@ -1,36 +1,31 @@
<h1>Download</h1>
<div class="box">
<form
hx-post="/api/download/add"
hx-trigger="submit"
hx-swap="none"
hx-on="htmx:afterRequest: this.reset()"
class="mb-4"
>
<div class="field">
<label class="label">Lien à débrider</label>
<div class="control">
<input class="input" type="text" name="link" placeholder="https://..." required>
</div>
</div>
<form hx-post="/api/download/add-multiple" hx-target="#downloads-table" class="p-4 space-y-4">
<label class="block">
<span class="text-sm font-medium">Liens à débrider (un par ligne)</span>
<textarea name="links" rows="5" class="w-full border rounded p-2" placeholder="http://...\nhttp://..."></textarea>
</label>
<div class="field">
<label class="label">Chemin d'enregistrement</label>
<div class="control">
<div class="select">
<select name="path_id">
{{range .paths}}<option value="{{.ID}}">{{.PathName}}</option>{{end}}
</select>
</div>
</div>
<label class="block">
<span class="text-sm font-medium">Dossier de destination</span>
<div class="flex space-x-2">
<select name="path_id" class="flex-1 border rounded p-2">
{{ range .paths }}
<option value="{{ .ID }}">{{ .Name }} ({{ .Path }})</option>
{{ end }}
</select>
<input type="text" name="new_subfolder" class="flex-1 border rounded p-2" placeholder="Créer un sous-dossier (optionnel)" />
</div>
</label>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">Ajouter</button>
</div>
</div>
</form>
<button type="submit" class="bg-indigo-600 text-white px-4 py-2 rounded">Télécharger</button>
</form>
<!-- Tableau des jobs -->
<div id="downloads-table">
{{ template "downloads_table" . }}
</div>
{{ end }}
<div
hx-ext="sse"
sse-connect="/api/download/stream"