package downloader import ( "context" "fmt" "m3u8-downloader/pkg/media" "net/url" "sync" "time" ) func resolveURL(baseURL string, segmentURL string) (string, error) { base, err := url.Parse(baseURL) if err != nil { return "", err } segment, err := url.Parse(segmentURL) if err != nil { return "", err } return base.ResolveReference(segment).String(), nil } func (s *DownloadService) DownloadWorker(id int, segmentChan <-chan media.Segment, wg *sync.WaitGroup, baseURL string) (int, int) { defer wg.Done() numErrors := 0 numDownloads := 0 for segment := range segmentChan { cleanedURL, err := resolveURL(baseURL, segment.URL) if err != nil { fmt.Printf("[Worker %d] Error: %s\n", id, err) return -1, -1 } fmt.Printf("[Worker %d] Downloading: %s\n", id, cleanedURL) downloadErr := s.DownloadFile(cleanedURL) if downloadErr != nil { if downloadErr.Error() == "HTTP 403: 403 Forbidden" { fmt.Printf("[Worker %d] URL Forbidden: %s\n", id, cleanedURL) numErrors++ continue } fmt.Printf("[Worker %d] Error: %s\n", id, downloadErr) numErrors++ return -1, -1 } numDownloads++ } return numErrors, numDownloads } func PlaylistRefreshWorker(ctx context.Context, playlistURL string, segmentsChan chan<- string, seen *sync.Map) { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: segments, err := GetSegmentURLs(playlistURL) if err != nil { fmt.Println(err) continue } for _, segment := range segments { if _, ok := seen.Load(segment); !ok { seen.Store(segment, true) }