up
This commit is contained in:
parent
5d1377dddb
commit
ebb2db9e39
@ -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, "_")
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user