abortPause #1
							
								
								
									
										21
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								main.go
									
									
									
									
									
								
							@@ -78,6 +78,7 @@ func startWebServer() {
 | 
			
		||||
	http.HandleFunc("/select", handleSelect)
 | 
			
		||||
	http.HandleFunc("/process", handleProcess)
 | 
			
		||||
	http.HandleFunc("/progress", handleProgress)
 | 
			
		||||
	http.HandleFunc("/abort", handleAbort)
 | 
			
		||||
 | 
			
		||||
	fmt.Println("Starting web server on http://0.0.0.0:8080")
 | 
			
		||||
	http.ListenAndServe(":8080", nil)
 | 
			
		||||
@@ -114,3 +115,23 @@ func parseMetadata(metadata string) Metadata {
 | 
			
		||||
		Season: "S" + strings.TrimSpace(parts[2]),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func handleAbort(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	filename := r.URL.Query().Get("filename")
 | 
			
		||||
	if filename == "" {
 | 
			
		||||
		http.Error(w, "Filename is required", http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jobsMutex.Lock()
 | 
			
		||||
	abortChan, exists := jobs[filename]
 | 
			
		||||
	jobsMutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	if !exists {
 | 
			
		||||
		http.Error(w, "Job not found", http.StatusNotFound)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(abortChan)
 | 
			
		||||
	fmt.Fprintf(w, "Abort signal sent for %s", filename)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,18 @@
 | 
			
		||||
            margin-top: 10px;
 | 
			
		||||
            word-wrap: break-word;
 | 
			
		||||
        }
 | 
			
		||||
        #abort-button {
 | 
			
		||||
            background-color: #f44336;
 | 
			
		||||
            color: white;
 | 
			
		||||
            border: none;
 | 
			
		||||
            padding: 10px 15px;
 | 
			
		||||
            margin-top: 10px;
 | 
			
		||||
            border-radius: 4px;
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
        }
 | 
			
		||||
        #abort-button:hover {
 | 
			
		||||
            background-color: #d32f2f;
 | 
			
		||||
        }
 | 
			
		||||
        @media (max-width: 600px) {
 | 
			
		||||
            body {
 | 
			
		||||
                padding: 10px;
 | 
			
		||||
@@ -84,6 +96,7 @@
 | 
			
		||||
        </div>
 | 
			
		||||
        <div id="currentFile"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <button id="abort-button" onclick="abortDownload()">Abort Download</button>
 | 
			
		||||
    <script>
 | 
			
		||||
        function updateProgress() {
 | 
			
		||||
            fetch('/progress?filename={{.Filename}}', {
 | 
			
		||||
@@ -103,6 +116,17 @@
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
        updateProgress();
 | 
			
		||||
 | 
			
		||||
        function abortDownload() {
 | 
			
		||||
            fetch('/abort?filename={{.Filename}}', { method: 'POST' })
 | 
			
		||||
                .then(response => {
 | 
			
		||||
                    if (response.ok) {
 | 
			
		||||
                        alert('Abort signal sent. The download will stop soon.');
 | 
			
		||||
                    } else {
 | 
			
		||||
                        alert('Failed to abort the download.');
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
    </script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								utils.go
									
									
									
									
									
								
							@@ -9,10 +9,16 @@ import (
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/beevik/etree"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	jobsMutex sync.Mutex
 | 
			
		||||
	jobs      = make(map[string]chan struct{})
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func sanitizeFilename(filename string) string {
 | 
			
		||||
	filename = regexp.MustCompile(`[<>:"/\\|?*]`).ReplaceAllString(filename, "_")
 | 
			
		||||
 | 
			
		||||
@@ -173,13 +179,30 @@ func filterSelectedItems(items []Item, selectedItems []string) []Item {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func processItems(filename string, items []Item) error {
 | 
			
		||||
	jobsMutex.Lock()
 | 
			
		||||
	abortChan := make(chan struct{})
 | 
			
		||||
	jobs[filename] = abortChan
 | 
			
		||||
	jobsMutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		jobsMutex.Lock()
 | 
			
		||||
		delete(jobs, filename)
 | 
			
		||||
		jobsMutex.Unlock()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	for i, item := range items {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-abortChan:
 | 
			
		||||
			updateProgress(filename, 100, "Aborted")
 | 
			
		||||
			return fmt.Errorf("download aborted")
 | 
			
		||||
		default:
 | 
			
		||||
			updateProgress(filename, float64(i)/float64(len(items))*100, item.Filename)
 | 
			
		||||
			err := downloadFile(item)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fmt.Printf("Error downloading file: %v\n", err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	updateProgress(filename, 100, "")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user